Merge tag 'ASB-2022-09-05_4.19-stable' of https://android.googlesource.com/kernel/common into android13-4.19-kona
https://source.android.com/docs/security/bulletin/2022-09-01 CVE-2022-20399 CVE-2022-23960 CVE-2021-4083 CVE-2022-29582 * tag 'ASB-2022-09-05_4.19-stable' of https://android.googlesource.com/kernel/common: Linux 4.19.255 x86/speculation: Add LFENCE to RSB fill sequence x86/speculation: Add RSB VM Exit protections macintosh/adb: fix oob read in do_adb_query() function ACPI: video: Shortening quirk list by identifying Clevo by board_name only ACPI: video: Force backlight native for some TongFang devices scsi: core: Fix race between handling STS_RESOURCE and completion mt7601u: add USB device ID for some versions of XiaoDu WiFi Dongle. ARM: crypto: comment out gcc warning that breaks clang builds perf symbol: Correct address for bss symbols netfilter: nf_queue: do not allow packet truncation below transport header offset sctp: fix sleep in atomic context bug in timer handlers i40e: Fix interface init with MSI interrupts (no MSI-X) tcp: Fix a data-race around sysctl_tcp_comp_sack_nr. tcp: Fix a data-race around sysctl_tcp_comp_sack_delay_ns. Documentation: fix sctp_wmem in ip-sysctl.rst tcp: Fix a data-race around sysctl_tcp_invalid_ratelimit. tcp: Fix a data-race around sysctl_tcp_autocorking. tcp: Fix a data-race around sysctl_tcp_min_rtt_wlen. tcp: Fix a data-race around sysctl_tcp_min_tso_segs. net: sungem_phy: Add of_node_put() for reference returned by of_get_parent() igmp: Fix data-races around sysctl_igmp_qrv. net: ping6: Fix memleak in ipv6_renew_options(). tcp: Fix a data-race around sysctl_tcp_challenge_ack_limit. scsi: ufs: host: Hold reference returned by of_parse_phandle() tcp: Fix a data-race around sysctl_tcp_nometrics_save. tcp: Fix a data-race around sysctl_tcp_frto. tcp: Fix a data-race around sysctl_tcp_adv_win_scale. tcp: Fix a data-race around sysctl_tcp_app_win. tcp: Fix data-races around sysctl_tcp_dsack. s390/archrandom: prevent CPACF trng invocations in interrupt context ntfs: fix use-after-free in ntfs_ucsncmp() Bluetooth: L2CAP: Fix use-after-free caused by l2cap_chan_put FROMLIST: binder: fix UAF of ref->proc caused by race condition Linux 4.19.254 PCI: hv: Fix interrupt mapping for multi-MSI PCI: hv: Reuse existing IRTE allocation in compose_msi_msg() PCI: hv: Fix hv_arch_irq_unmask() for multi-MSI PCI: hv: Fix multi-MSI to allow more than one MSI vector net: usb: ax88179_178a needs FLAG_SEND_ZLP tty: use new tty_insert_flip_string_and_push_buffer() in pty_write() tty: extract tty_flip_buffer_commit() from tty_flip_buffer_push() tty: drop tty_schedule_flip() tty: the rest, stop using tty_schedule_flip() tty: drivers/tty/, stop using tty_schedule_flip() serial: mvebu-uart: correctly report configured baudrate value Bluetooth: Fix bt_skb_sendmmsg not allocating partial chunks Bluetooth: SCO: Fix sco_send_frame returning skb->len Bluetooth: Fix passing NULL to PTR_ERR Bluetooth: RFCOMM: Replace use of memcpy_from_msg with bt_skb_sendmmsg Bluetooth: SCO: Replace use of memcpy_from_msg with bt_skb_sendmsg Bluetooth: Add bt_skb_sendmmsg helper Bluetooth: Add bt_skb_sendmsg helper ALSA: memalloc: Align buffer allocations in page size ima: remove the IMA_TEMPLATE Kconfig option dlm: fix pending remove if msg allocation fails HID: add ALWAYS_POLL quirk to lenovo pixart mouse HID: multitouch: add support for the Smart Tech panel HID: multitouch: Lenovo X1 Tablet Gen3 trackpoint and buttons HID: multitouch: simplify the application retrieval tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator drm/tilcdc: Remove obsolete crtc_mode_valid() hack bpf: Make sure mac_header was set before using it mm/mempolicy: fix uninit-value in mpol_rebind_policy() Revert "Revert "char/random: silence a lockdep splat with printk()"" tcp: Fix data-races around sysctl_tcp_max_reordering. tcp: Fix a data-race around sysctl_tcp_rfc1337. tcp: Fix a data-race around sysctl_tcp_stdurg. tcp: Fix a data-race around sysctl_tcp_retrans_collapse. tcp: Fix data-races around sysctl_tcp_slow_start_after_idle. tcp: Fix a data-race around sysctl_tcp_thin_linear_timeouts. tcp: Fix data-races around sysctl_tcp_recovery. tcp: Fix a data-race around sysctl_tcp_early_retrans. be2net: Fix buffer overflow in be_get_module_eeprom tcp: Fix data-races around sysctl_tcp_fastopen. tcp: Fix a data-race around sysctl_tcp_tw_reuse. tcp: Fix a data-race around sysctl_tcp_notsent_lowat. tcp: Fix data-races around some timeout sysctl knobs. tcp: Fix data-races around sysctl_tcp_reordering. igmp: Fix a data-race around sysctl_igmp_max_memberships. igmp: Fix data-races around sysctl_igmp_llm_reports. net/tls: Fix race in TLS device down flow net: stmmac: fix dma queue left shift overflow issue i2c: cadence: Change large transfer count reset logic to be unconditional tcp: Fix a data-race around sysctl_tcp_probe_interval. tcp: Fix a data-race around sysctl_tcp_probe_threshold. tcp: Fix data-races around sysctl_tcp_mtu_probing. tcp/dccp: Fix a data-race around sysctl_tcp_fwmark_accept. ip: Fix a data-race around sysctl_fwmark_reflect. ip: Fix data-races around sysctl_ip_nonlocal_bind. ip: Fix data-races around sysctl_ip_fwd_use_pmtu. perf/core: Fix data race between perf_event_set_output() and perf_mmap_close() pinctrl: ralink: Check for null return of devm_kcalloc power/reset: arm-versatile: Fix refcount leak in versatile_reboot_probe xfrm: xfrm_policy: fix a possible double xfrm_pols_put() in xfrm_bundle_lookup() xen/gntdev: Ignore failure to unmap INVALID_GRANT_HANDLE riscv: add as-options for modules with assembly compontents Revert "cgroup: Use separate src/dst nodes when preloading css_sets for migration" Linux 4.19.253 can: m_can: m_can_tx_handler(): fix use after free of skb serial: pl011: UPSTAT_AUTORTS requires .throttle/unthrottle serial: stm32: Clear prev values before setting RTS delays serial: 8250: fix return error code in serial8250_request_std_resource() tty: serial: samsung_tty: set dma burst_size to 1 usb: dwc3: gadget: Fix event pending check usb: typec: add missing uevent when partner support PD USB: serial: ftdi_sio: add Belimo device ids signal handling: don't use BUG_ON() for debugging ARM: dts: stm32: use the correct clock source for CEC on stm32mp151 x86: Clear .brk area at early boot irqchip: or1k-pic: Undefine mask_ack for level triggered hardware ASoC: wm5110: Fix DRE control ASoC: ops: Fix off by one in range control validation net: sfp: fix memory leak in sfp_probe() NFC: nxp-nci: don't print header length mismatch on i2c error net: tipc: fix possible refcount leak in tipc_sk_create() platform/x86: hp-wmi: Ignore Sanitization Mode event cpufreq: pmac32-cpufreq: Fix refcount leak bug netfilter: br_netfilter: do not skip all hooks with 0 priority virtio_mmio: Restore guest page size on resume virtio_mmio: Add missing PM calls to freeze/restore sfc: fix kernel panic when creating VF seg6: bpf: fix skb checksum in bpf_push_seg6_encap() seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors seg6: fix skb checksum evaluation in SRH encapsulation/insertion sfc: fix use after free when disabling sriov ipv4: Fix data-races around sysctl_ip_dynaddr. icmp: Fix a data-race around sysctl_icmp_ratemask. icmp: Fix a data-race around sysctl_icmp_ratelimit. ARM: dts: sunxi: Fix SPI NOR campatible on Orange Pi Zero icmp: Fix data-races around sysctl. cipso: Fix data-races around sysctl. net: Fix data-races around sysctl_mem. inetpeer: Fix data-races around sysctl. ASoC: sgtl5000: Fix noise on shutdown/remove ARM: 9209/1: Spectre-BHB: avoid pr_info() every time a CPU comes out of idle ARM: dts: imx6qdl-ts7970: Fix ngpio typo and count nilfs2: fix incorrect masking of permission flags for symlinks cgroup: Use separate src/dst nodes when preloading css_sets for migration ARM: 9214/1: alignment: advance IT state after emulating Thumb instruction ARM: 9213/1: Print message about disabled Spectre workarounds only once net: sock: tracing: Fix sock_exceed_buf_limit not to dereference stale pointer tracing/histograms: Fix memory leak problem xen/netback: avoid entering xenvif_rx_next_skb() with an empty rx queue ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc221 ALSA: hda/conexant: Apply quirk for another HP ProDesk 600 G3 model ALSA: hda - Add fixup for Dell Latitidue E5430 Change-Id: I2ea45f6f13cf904894563522f1bb35830dd0bf9e
This commit is contained in:
commit
ee48262ac6
133 changed files with 1104 additions and 623 deletions
|
@ -422,6 +422,14 @@ The possible values in this file are:
|
|||
'RSB filling' Protection of RSB on context switch enabled
|
||||
============= ===========================================
|
||||
|
||||
- EIBRS Post-barrier Return Stack Buffer (PBRSB) protection status:
|
||||
|
||||
=========================== =======================================================
|
||||
'PBRSB-eIBRS: SW sequence' CPU is affected and protection of RSB on VMEXIT enabled
|
||||
'PBRSB-eIBRS: Vulnerable' CPU is vulnerable
|
||||
'PBRSB-eIBRS: Not affected' CPU is not affected by PBRSB
|
||||
=========================== =======================================================
|
||||
|
||||
Full mitigation might require a microcode update from the CPU
|
||||
vendor. When the necessary microcode is not available, the kernel will
|
||||
report vulnerability.
|
||||
|
|
|
@ -820,7 +820,7 @@ cipso_cache_enable - BOOLEAN
|
|||
cipso_cache_bucket_size - INTEGER
|
||||
The CIPSO label cache consists of a fixed size hash table with each
|
||||
hash bucket containing a number of cache entries. This variable limits
|
||||
the number of entries in each hash bucket; the larger the value the
|
||||
the number of entries in each hash bucket; the larger the value is, the
|
||||
more CIPSO label mappings that can be cached. When the number of
|
||||
entries in a given hash bucket reaches this limit adding new entries
|
||||
causes the oldest entry in the bucket to be removed to make room.
|
||||
|
@ -902,7 +902,7 @@ ip_nonlocal_bind - BOOLEAN
|
|||
which can be quite useful - but may break some applications.
|
||||
Default: 0
|
||||
|
||||
ip_dynaddr - BOOLEAN
|
||||
ip_dynaddr - INTEGER
|
||||
If set non-zero, enables support for dynamic addresses.
|
||||
If set to a non-zero value larger than 1, a kernel log
|
||||
message will be printed when dynamic address rewriting
|
||||
|
@ -2189,7 +2189,14 @@ sctp_rmem - vector of 3 INTEGERs: min, default, max
|
|||
Default: 4K
|
||||
|
||||
sctp_wmem - vector of 3 INTEGERs: min, default, max
|
||||
Currently this tunable has no effect.
|
||||
Only the first value ("min") is used, "default" and "max" are
|
||||
ignored.
|
||||
|
||||
min: Minimum size of send buffer that can be used by SCTP sockets.
|
||||
It is guaranteed to each SCTP socket (but not association) even
|
||||
under moderate memory pressure.
|
||||
|
||||
Default: 4K
|
||||
|
||||
addr_scope_policy - INTEGER
|
||||
Control IPv4 address scoping - draft-stewart-tsvwg-sctp-ipv4-00
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 19
|
||||
SUBLEVEL = 252
|
||||
SUBLEVEL = 255
|
||||
EXTRAVERSION =
|
||||
NAME = "People's Front"
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ srmcons_do_receive_chars(struct tty_port *port)
|
|||
} while((result.bits.status & 1) && (++loops < 10));
|
||||
|
||||
if (count)
|
||||
tty_schedule_flip(port);
|
||||
tty_flip_buffer_push(port);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@
|
|||
reg = <0x28>;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
ngpio = <32>;
|
||||
ngpios = <62>;
|
||||
};
|
||||
|
||||
sgtl5000: codec@a {
|
||||
|
|
|
@ -413,7 +413,7 @@
|
|||
compatible = "st,stm32-cec";
|
||||
reg = <0x40016000 0x400>;
|
||||
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc CEC_K>, <&clk_lse>;
|
||||
clocks = <&rcc CEC_K>, <&rcc CEC>;
|
||||
clock-names = "cec", "hdmi-cec";
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -170,7 +170,7 @@
|
|||
flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "mxicy,mx25l1606e", "winbond,w25q128";
|
||||
compatible = "mxicy,mx25l1606e", "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <40000000>;
|
||||
};
|
||||
|
|
|
@ -167,5 +167,31 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
|
|||
((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1; \
|
||||
})
|
||||
|
||||
|
||||
/*
|
||||
* Update ITSTATE after normal execution of an IT block instruction.
|
||||
*
|
||||
* The 8 IT state bits are split into two parts in CPSR:
|
||||
* ITSTATE<1:0> are in CPSR<26:25>
|
||||
* ITSTATE<7:2> are in CPSR<15:10>
|
||||
*/
|
||||
static inline unsigned long it_advance(unsigned long cpsr)
|
||||
{
|
||||
if ((cpsr & 0x06000400) == 0) {
|
||||
/* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
|
||||
cpsr &= ~PSR_IT_MASK;
|
||||
} else {
|
||||
/* We need to shift left ITSTATE<4:0> */
|
||||
const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */
|
||||
unsigned long it = cpsr & mask;
|
||||
it <<= 1;
|
||||
it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */
|
||||
it &= mask;
|
||||
cpsr &= ~mask;
|
||||
cpsr |= it;
|
||||
}
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif
|
||||
|
|
|
@ -29,8 +29,9 @@ MODULE_LICENSE("GPL");
|
|||
* While older versions of GCC do not generate incorrect code, they fail to
|
||||
* recognize the parallel nature of these functions, and emit plain ARM code,
|
||||
* which is known to be slower than the optimized ARM code in asm-arm/xor.h.
|
||||
*
|
||||
* #warning This code requires at least version 4.6 of GCC
|
||||
*/
|
||||
#warning This code requires at least version 4.6 of GCC
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
|
|
|
@ -936,6 +936,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
if (type == TYPE_LDST)
|
||||
do_alignment_finish_ldst(addr, instr, regs, offset);
|
||||
|
||||
if (thumb_mode(regs))
|
||||
regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
|
||||
|
||||
return 0;
|
||||
|
||||
bad_or_fault:
|
||||
|
|
|
@ -110,8 +110,7 @@ static unsigned int spectre_v2_install_workaround(unsigned int method)
|
|||
#else
|
||||
static unsigned int spectre_v2_install_workaround(unsigned int method)
|
||||
{
|
||||
pr_info("CPU%u: Spectre V2: workarounds disabled by configuration\n",
|
||||
smp_processor_id());
|
||||
pr_info_once("Spectre V2: workarounds disabled by configuration\n");
|
||||
|
||||
return SPECTRE_VULNERABLE;
|
||||
}
|
||||
|
@ -223,10 +222,10 @@ static int spectre_bhb_install_workaround(int method)
|
|||
return SPECTRE_VULNERABLE;
|
||||
|
||||
spectre_bhb_method = method;
|
||||
}
|
||||
|
||||
pr_info("CPU%u: Spectre BHB: using %s workaround\n",
|
||||
pr_info("CPU%u: Spectre BHB: enabling %s workaround for all CPUs\n",
|
||||
smp_processor_id(), spectre_bhb_method_name(method));
|
||||
}
|
||||
|
||||
return SPECTRE_MITIGATED;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <asm/probes.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/kprobes.h>
|
||||
|
||||
void __init arm_probes_decode_init(void);
|
||||
|
@ -43,31 +44,6 @@ void __init find_str_pc_offset(void);
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Update ITSTATE after normal execution of an IT block instruction.
|
||||
*
|
||||
* The 8 IT state bits are split into two parts in CPSR:
|
||||
* ITSTATE<1:0> are in CPSR<26:25>
|
||||
* ITSTATE<7:2> are in CPSR<15:10>
|
||||
*/
|
||||
static inline unsigned long it_advance(unsigned long cpsr)
|
||||
{
|
||||
if ((cpsr & 0x06000400) == 0) {
|
||||
/* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
|
||||
cpsr &= ~PSR_IT_MASK;
|
||||
} else {
|
||||
/* We need to shift left ITSTATE<4:0> */
|
||||
const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */
|
||||
unsigned long it = cpsr & mask;
|
||||
it <<= 1;
|
||||
it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */
|
||||
it &= mask;
|
||||
cpsr &= ~mask;
|
||||
cpsr |= it;
|
||||
}
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
|
||||
{
|
||||
long cpsr = regs->ARM_cpsr;
|
||||
|
|
|
@ -66,6 +66,7 @@ ifeq ($(CONFIG_MODULE_SECTIONS),y)
|
|||
endif
|
||||
|
||||
KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax)
|
||||
KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax)
|
||||
|
||||
# GCC versions that support the "-mstrict-align" option default to allowing
|
||||
# unaligned accesses. While unaligned accesses are explicitly allowed in the
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Kernel interface for the s390 arch_random_* functions
|
||||
*
|
||||
* Copyright IBM Corp. 2017, 2020
|
||||
* Copyright IBM Corp. 2017, 2022
|
||||
*
|
||||
* Author: Harald Freudenberger <freude@de.ibm.com>
|
||||
*
|
||||
|
@ -14,6 +14,7 @@
|
|||
#ifdef CONFIG_ARCH_RANDOM
|
||||
|
||||
#include <linux/static_key.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/cpacf.h>
|
||||
|
||||
|
@ -32,7 +33,8 @@ static inline bool __must_check arch_get_random_int(unsigned int *v)
|
|||
|
||||
static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
|
||||
{
|
||||
if (static_branch_likely(&s390_arch_random_available)) {
|
||||
if (static_branch_likely(&s390_arch_random_available) &&
|
||||
in_task()) {
|
||||
cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
|
||||
atomic64_add(sizeof(*v), &s390_arch_random_counter);
|
||||
return true;
|
||||
|
@ -42,7 +44,8 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
|
|||
|
||||
static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
|
||||
{
|
||||
if (static_branch_likely(&s390_arch_random_available)) {
|
||||
if (static_branch_likely(&s390_arch_random_available) &&
|
||||
in_task()) {
|
||||
cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
|
||||
atomic64_add(sizeof(*v), &s390_arch_random_counter);
|
||||
return true;
|
||||
|
|
|
@ -283,6 +283,7 @@
|
|||
#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* LLC Local MBM monitoring */
|
||||
#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
|
||||
#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
|
||||
#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+ 6) /* "" Fill RSB on VM exit when EIBRS is enabled */
|
||||
|
||||
/* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
|
||||
#define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */
|
||||
|
@ -395,5 +396,6 @@
|
|||
#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
|
||||
#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
|
||||
#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
|
||||
#define X86_BUG_EIBRS_PBRSB X86_BUG(26) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
|
||||
|
||||
#endif /* _ASM_X86_CPUFEATURES_H */
|
||||
|
|
|
@ -120,6 +120,10 @@
|
|||
* bit available to control VERW
|
||||
* behavior.
|
||||
*/
|
||||
#define ARCH_CAP_PBRSB_NO BIT(24) /*
|
||||
* Not susceptible to Post-Barrier
|
||||
* Return Stack Buffer Predictions.
|
||||
*/
|
||||
|
||||
#define MSR_IA32_FLUSH_CMD 0x0000010b
|
||||
#define L1D_FLUSH BIT(0) /*
|
||||
|
|
|
@ -52,7 +52,17 @@
|
|||
774: \
|
||||
dec reg; \
|
||||
jnz 771b; \
|
||||
add $(BITS_PER_LONG/8) * nr, sp;
|
||||
add $(BITS_PER_LONG/8) * nr, sp; \
|
||||
/* barrier for jnz misprediction */ \
|
||||
lfence;
|
||||
|
||||
/* Sequence to mitigate PBRSB on eIBRS CPUs */
|
||||
#define __ISSUE_UNBALANCED_RET_GUARD(sp) \
|
||||
call 881f; \
|
||||
int3; \
|
||||
881: \
|
||||
add $(BITS_PER_LONG/8), sp; \
|
||||
lfence;
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
|
@ -269,6 +279,13 @@ static inline void vmexit_fill_RSB(void)
|
|||
: "=r" (loops), ASM_CALL_CONSTRAINT
|
||||
: : "memory" );
|
||||
#endif
|
||||
asm volatile (ANNOTATE_NOSPEC_ALTERNATIVE
|
||||
ALTERNATIVE("jmp 920f",
|
||||
__stringify(__ISSUE_UNBALANCED_RET_GUARD(%0)),
|
||||
X86_FEATURE_RSB_VMEXIT_LITE)
|
||||
"920:"
|
||||
: ASM_CALL_CONSTRAINT
|
||||
: : "memory" );
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
|
|
|
@ -1043,6 +1043,49 @@ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void)
|
|||
return SPECTRE_V2_RETPOLINE;
|
||||
}
|
||||
|
||||
static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode)
|
||||
{
|
||||
/*
|
||||
* Similar to context switches, there are two types of RSB attacks
|
||||
* after VM exit:
|
||||
*
|
||||
* 1) RSB underflow
|
||||
*
|
||||
* 2) Poisoned RSB entry
|
||||
*
|
||||
* When retpoline is enabled, both are mitigated by filling/clearing
|
||||
* the RSB.
|
||||
*
|
||||
* When IBRS is enabled, while #1 would be mitigated by the IBRS branch
|
||||
* prediction isolation protections, RSB still needs to be cleared
|
||||
* because of #2. Note that SMEP provides no protection here, unlike
|
||||
* user-space-poisoned RSB entries.
|
||||
*
|
||||
* eIBRS should protect against RSB poisoning, but if the EIBRS_PBRSB
|
||||
* bug is present then a LITE version of RSB protection is required,
|
||||
* just a single call needs to retire before a RET is executed.
|
||||
*/
|
||||
switch (mode) {
|
||||
case SPECTRE_V2_NONE:
|
||||
/* These modes already fill RSB at vmexit */
|
||||
case SPECTRE_V2_LFENCE:
|
||||
case SPECTRE_V2_RETPOLINE:
|
||||
case SPECTRE_V2_EIBRS_RETPOLINE:
|
||||
return;
|
||||
|
||||
case SPECTRE_V2_EIBRS_LFENCE:
|
||||
case SPECTRE_V2_EIBRS:
|
||||
if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
|
||||
setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT_LITE);
|
||||
pr_info("Spectre v2 / PBRSB-eIBRS: Retire a single CALL on VMEXIT\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pr_warn_once("Unknown Spectre v2 mode, disabling RSB mitigation at VM exit");
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
static void __init spectre_v2_select_mitigation(void)
|
||||
{
|
||||
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
|
||||
|
@ -1135,6 +1178,8 @@ static void __init spectre_v2_select_mitigation(void)
|
|||
setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
|
||||
pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");
|
||||
|
||||
spectre_v2_determine_rsb_fill_type_at_vmexit(mode);
|
||||
|
||||
/*
|
||||
* Retpoline means the kernel is safe because it has no indirect
|
||||
* branches. Enhanced IBRS protects firmware too, so, enable restricted
|
||||
|
@ -1867,6 +1912,19 @@ static char *ibpb_state(void)
|
|||
return "";
|
||||
}
|
||||
|
||||
static char *pbrsb_eibrs_state(void)
|
||||
{
|
||||
if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
|
||||
if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) ||
|
||||
boot_cpu_has(X86_FEATURE_RETPOLINE))
|
||||
return ", PBRSB-eIBRS: SW sequence";
|
||||
else
|
||||
return ", PBRSB-eIBRS: Vulnerable";
|
||||
} else {
|
||||
return ", PBRSB-eIBRS: Not affected";
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t spectre_v2_show_state(char *buf)
|
||||
{
|
||||
if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
|
||||
|
@ -1879,12 +1937,13 @@ static ssize_t spectre_v2_show_state(char *buf)
|
|||
spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
|
||||
return sprintf(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
|
||||
|
||||
return sprintf(buf, "%s%s%s%s%s%s\n",
|
||||
return sprintf(buf, "%s%s%s%s%s%s%s\n",
|
||||
spectre_v2_strings[spectre_v2_enabled],
|
||||
ibpb_state(),
|
||||
boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
|
||||
stibp_state(),
|
||||
boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
|
||||
pbrsb_eibrs_state(),
|
||||
spectre_v2_module_string());
|
||||
}
|
||||
|
||||
|
|
|
@ -954,6 +954,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
|
|||
#define MSBDS_ONLY BIT(5)
|
||||
#define NO_SWAPGS BIT(6)
|
||||
#define NO_ITLB_MULTIHIT BIT(7)
|
||||
#define NO_EIBRS_PBRSB BIT(8)
|
||||
|
||||
#define VULNWL(_vendor, _family, _model, _whitelist) \
|
||||
{ X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
|
||||
|
@ -990,7 +991,7 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
|||
|
||||
VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
||||
VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
||||
VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
||||
VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
|
||||
|
||||
/*
|
||||
* Technically, swapgs isn't serializing on AMD (despite it previously
|
||||
|
@ -1000,7 +1001,9 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
|||
* good enough for our purposes.
|
||||
*/
|
||||
|
||||
VULNWL_INTEL(ATOM_TREMONT_X, NO_ITLB_MULTIHIT),
|
||||
VULNWL_INTEL(ATOM_TREMONT, NO_EIBRS_PBRSB),
|
||||
VULNWL_INTEL(ATOM_TREMONT_L, NO_EIBRS_PBRSB),
|
||||
VULNWL_INTEL(ATOM_TREMONT_X, NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
|
||||
|
||||
/* AMD Family 0xf - 0x12 */
|
||||
VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
||||
|
@ -1154,6 +1157,11 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
|||
!arch_cap_mmio_immune(ia32_cap))
|
||||
setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_IBRS_ENHANCED) &&
|
||||
!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
|
||||
!(ia32_cap & ARCH_CAP_PBRSB_NO))
|
||||
setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
|
||||
|
||||
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
|
||||
return;
|
||||
|
||||
|
|
|
@ -383,6 +383,8 @@ static void __init clear_bss(void)
|
|||
{
|
||||
memset(__bss_start, 0,
|
||||
(unsigned long) __bss_stop - (unsigned long) __bss_start);
|
||||
memset(__brk_base, 0,
|
||||
(unsigned long) __brk_limit - (unsigned long) __brk_base);
|
||||
}
|
||||
|
||||
static unsigned long get_cmd_line_ptr(void)
|
||||
|
|
|
@ -10988,6 +10988,9 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
#endif
|
||||
);
|
||||
|
||||
/* Eliminate branch target predictions from guest mode */
|
||||
vmexit_fill_RSB();
|
||||
|
||||
vmx_enable_fb_clear(vmx);
|
||||
|
||||
/*
|
||||
|
@ -11010,9 +11013,6 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
|
||||
x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0);
|
||||
|
||||
/* Eliminate branch target predictions from guest mode */
|
||||
vmexit_fill_RSB();
|
||||
|
||||
/* All fields are clean at this point */
|
||||
if (static_branch_unlikely(&enable_evmcs))
|
||||
current_evmcs->hv_clean_fields |=
|
||||
|
|
|
@ -371,23 +371,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xRU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
||||
},
|
||||
},
|
||||
|
@ -410,28 +393,60 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xNU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
|
||||
},
|
||||
},
|
||||
/*
|
||||
* The TongFang PF5PU1G, PF4NU1F, PF5NU1G, and PF5LUXG/TUXEDO BA15 Gen10,
|
||||
* Pulse 14/15 Gen1, and Pulse 15 Gen2 have the same problem as the Clevo
|
||||
* NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2. See the description
|
||||
* above.
|
||||
*/
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF5PU1G",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF4NU1F",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PF4NU1F"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF4NU1F",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PULSE1401"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xNU",
|
||||
.ident = "TongFang PF5NU1G",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PF5NU1G"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "Clevo NL5xNU",
|
||||
.ident = "TongFang PF5NU1G",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PULSE1501"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
.ident = "TongFang PF5LUXG",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Desktops which falsely report a backlight and which our heuristics
|
||||
* for this do not catch.
|
||||
|
|
|
@ -183,7 +183,7 @@ static void __cold process_random_ready_list(void)
|
|||
|
||||
#define warn_unseeded_randomness() \
|
||||
if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \
|
||||
pr_notice("%s called from %pS with crng_init=%d\n", \
|
||||
printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \
|
||||
__func__, (void *)_RET_IP_, crng_init)
|
||||
|
||||
|
||||
|
|
|
@ -474,6 +474,10 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
|
|||
if (slew_done_gpio_np)
|
||||
slew_done_gpio = read_gpio(slew_done_gpio_np);
|
||||
|
||||
of_node_put(volt_gpio_np);
|
||||
of_node_put(freq_gpio_np);
|
||||
of_node_put(slew_done_gpio_np);
|
||||
|
||||
/* If we use the frequency GPIOs, calculate the min/max speeds based
|
||||
* on the bus frequencies
|
||||
*/
|
||||
|
|
|
@ -657,9 +657,6 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
|
|||
static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
struct drm_display_mode *mode = &state->mode;
|
||||
int ret;
|
||||
|
||||
/* If we are not active we don't care */
|
||||
if (!state->active)
|
||||
return 0;
|
||||
|
@ -671,12 +668,6 @@ static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = tilcdc_crtc_mode_valid(crtc, mode);
|
||||
if (ret) {
|
||||
dev_dbg(crtc->dev->dev, "Mode \"%s\" not valid", mode->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -728,13 +719,6 @@ static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
|
|||
.disable_vblank = tilcdc_crtc_disable_vblank,
|
||||
};
|
||||
|
||||
static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
|
||||
.mode_fixup = tilcdc_crtc_mode_fixup,
|
||||
.atomic_check = tilcdc_crtc_atomic_check,
|
||||
.atomic_enable = tilcdc_crtc_atomic_enable,
|
||||
.atomic_disable = tilcdc_crtc_atomic_disable,
|
||||
};
|
||||
|
||||
int tilcdc_crtc_max_width(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -749,7 +733,9 @@ int tilcdc_crtc_max_width(struct drm_crtc *crtc)
|
|||
return max_width;
|
||||
}
|
||||
|
||||
int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
static enum drm_mode_status
|
||||
tilcdc_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = crtc->dev->dev_private;
|
||||
unsigned int bandwidth;
|
||||
|
@ -837,6 +823,14 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
return MODE_OK;
|
||||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
|
||||
.mode_valid = tilcdc_crtc_mode_valid,
|
||||
.mode_fixup = tilcdc_crtc_mode_fixup,
|
||||
.atomic_check = tilcdc_crtc_atomic_check,
|
||||
.atomic_enable = tilcdc_crtc_atomic_enable,
|
||||
.atomic_disable = tilcdc_crtc_atomic_disable,
|
||||
};
|
||||
|
||||
void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
|
||||
const struct tilcdc_panel_info *info)
|
||||
{
|
||||
|
|
|
@ -202,7 +202,6 @@ static void tilcdc_fini(struct drm_device *dev)
|
|||
|
||||
drm_irq_uninstall(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
tilcdc_remove_external_device(dev);
|
||||
|
||||
if (priv->clk)
|
||||
clk_put(priv->clk);
|
||||
|
|
|
@ -89,7 +89,6 @@ struct tilcdc_drm_private {
|
|||
|
||||
struct drm_encoder *external_encoder;
|
||||
struct drm_connector *external_connector;
|
||||
const struct drm_connector_helper_funcs *connector_funcs;
|
||||
|
||||
bool is_registered;
|
||||
bool is_componentized;
|
||||
|
@ -171,7 +170,6 @@ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
|
|||
const struct tilcdc_panel_info *info);
|
||||
void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
|
||||
bool simulate_vesa_sync);
|
||||
int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
|
||||
int tilcdc_crtc_max_width(struct drm_crtc *crtc);
|
||||
void tilcdc_crtc_shutdown(struct drm_crtc *crtc);
|
||||
int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
|
||||
|
|
|
@ -40,64 +40,6 @@ static const struct tilcdc_panel_info panel_info_default = {
|
|||
.raster_order = 0,
|
||||
};
|
||||
|
||||
static int tilcdc_external_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = connector->dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = tilcdc_crtc_mode_valid(priv->crtc, mode);
|
||||
if (ret != MODE_OK)
|
||||
return ret;
|
||||
|
||||
BUG_ON(priv->external_connector != connector);
|
||||
BUG_ON(!priv->connector_funcs);
|
||||
|
||||
/* If the connector has its own mode_valid call it. */
|
||||
if (!IS_ERR(priv->connector_funcs) &&
|
||||
priv->connector_funcs->mode_valid)
|
||||
return priv->connector_funcs->mode_valid(connector, mode);
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static int tilcdc_add_external_connector(struct drm_device *dev,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||
struct drm_connector_helper_funcs *connector_funcs;
|
||||
|
||||
/* There should never be more than one connector */
|
||||
if (WARN_ON(priv->external_connector))
|
||||
return -EINVAL;
|
||||
|
||||
priv->external_connector = connector;
|
||||
connector_funcs = devm_kzalloc(dev->dev, sizeof(*connector_funcs),
|
||||
GFP_KERNEL);
|
||||
if (!connector_funcs)
|
||||
return -ENOMEM;
|
||||
|
||||
/* connector->helper_private contains always struct
|
||||
* connector_helper_funcs pointer. For tilcdc crtc to have a
|
||||
* say if a specific mode is Ok, we need to install our own
|
||||
* helper functions. In our helper functions we copy
|
||||
* everything else but use our own mode_valid() (above).
|
||||
*/
|
||||
if (connector->helper_private) {
|
||||
priv->connector_funcs = connector->helper_private;
|
||||
*connector_funcs = *priv->connector_funcs;
|
||||
} else {
|
||||
priv->connector_funcs = ERR_PTR(-ENOENT);
|
||||
}
|
||||
connector_funcs->mode_valid = tilcdc_external_mode_valid;
|
||||
drm_connector_helper_add(connector, connector_funcs);
|
||||
|
||||
dev_dbg(dev->dev, "External connector '%s' connected\n",
|
||||
connector->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev,
|
||||
struct drm_encoder *encoder)
|
||||
|
@ -118,40 +60,30 @@ struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev,
|
|||
int tilcdc_add_component_encoder(struct drm_device *ddev)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = ddev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_encoder *encoder = NULL, *iter;
|
||||
|
||||
list_for_each_entry(encoder, &ddev->mode_config.encoder_list, head)
|
||||
if (encoder->possible_crtcs & (1 << priv->crtc->index))
|
||||
list_for_each_entry(iter, &ddev->mode_config.encoder_list, head)
|
||||
if (iter->possible_crtcs & (1 << priv->crtc->index)) {
|
||||
encoder = iter;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!encoder) {
|
||||
dev_err(ddev->dev, "%s: No suitable encoder found\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
connector = tilcdc_encoder_find_connector(ddev, encoder);
|
||||
priv->external_connector =
|
||||
tilcdc_encoder_find_connector(ddev, encoder);
|
||||
|
||||
if (!connector)
|
||||
if (!priv->external_connector)
|
||||
return -ENODEV;
|
||||
|
||||
/* Only tda998x is supported at the moment. */
|
||||
tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true);
|
||||
tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x);
|
||||
|
||||
return tilcdc_add_external_connector(ddev, connector);
|
||||
}
|
||||
|
||||
void tilcdc_remove_external_device(struct drm_device *dev)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||
|
||||
/* Restore the original helper functions, if any. */
|
||||
if (IS_ERR(priv->connector_funcs))
|
||||
drm_connector_helper_add(priv->external_connector, NULL);
|
||||
else if (priv->connector_funcs)
|
||||
drm_connector_helper_add(priv->external_connector,
|
||||
priv->connector_funcs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs tilcdc_external_encoder_funcs = {
|
||||
|
@ -162,7 +94,6 @@ static
|
|||
int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = ddev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
|
||||
priv->external_encoder->possible_crtcs = BIT(0);
|
||||
|
@ -175,13 +106,12 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
|
|||
|
||||
tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default);
|
||||
|
||||
connector = tilcdc_encoder_find_connector(ddev, priv->external_encoder);
|
||||
if (!connector)
|
||||
priv->external_connector =
|
||||
tilcdc_encoder_find_connector(ddev, priv->external_encoder);
|
||||
if (!priv->external_connector)
|
||||
return -ENODEV;
|
||||
|
||||
ret = tilcdc_add_external_connector(ddev, connector);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tilcdc_attach_external_device(struct drm_device *ddev)
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#define __TILCDC_EXTERNAL_H__
|
||||
|
||||
int tilcdc_add_component_encoder(struct drm_device *dev);
|
||||
void tilcdc_remove_external_device(struct drm_device *dev);
|
||||
int tilcdc_get_external_components(struct device *dev,
|
||||
struct component_match **match);
|
||||
int tilcdc_attach_external_device(struct drm_device *ddev);
|
||||
|
|
|
@ -174,14 +174,6 @@ static int panel_connector_get_modes(struct drm_connector *connector)
|
|||
return i;
|
||||
}
|
||||
|
||||
static int panel_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = connector->dev->dev_private;
|
||||
/* our only constraints are what the crtc can generate: */
|
||||
return tilcdc_crtc_mode_valid(priv->crtc, mode);
|
||||
}
|
||||
|
||||
static struct drm_encoder *panel_connector_best_encoder(
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
|
@ -199,7 +191,6 @@ static const struct drm_connector_funcs panel_connector_funcs = {
|
|||
|
||||
static const struct drm_connector_helper_funcs panel_connector_helper_funcs = {
|
||||
.get_modes = panel_connector_get_modes,
|
||||
.mode_valid = panel_connector_mode_valid,
|
||||
.best_encoder = panel_connector_best_encoder,
|
||||
};
|
||||
|
||||
|
|
|
@ -183,14 +183,6 @@ static int tfp410_connector_get_modes(struct drm_connector *connector)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tfp410_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = connector->dev->dev_private;
|
||||
/* our only constraints are what the crtc can generate: */
|
||||
return tilcdc_crtc_mode_valid(priv->crtc, mode);
|
||||
}
|
||||
|
||||
static struct drm_encoder *tfp410_connector_best_encoder(
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
|
@ -209,7 +201,6 @@ static const struct drm_connector_funcs tfp410_connector_funcs = {
|
|||
|
||||
static const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = {
|
||||
.get_modes = tfp410_connector_get_modes,
|
||||
.mode_valid = tfp410_connector_mode_valid,
|
||||
.best_encoder = tfp410_connector_best_encoder,
|
||||
};
|
||||
|
||||
|
|
|
@ -727,6 +727,8 @@
|
|||
#define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067
|
||||
#define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085
|
||||
#define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3
|
||||
#define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5
|
||||
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d
|
||||
|
||||
#define USB_VENDOR_ID_LG 0x1fd2
|
||||
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
|
||||
|
|
|
@ -72,6 +72,7 @@ MODULE_LICENSE("GPL");
|
|||
#define MT_QUIRK_STICKY_FINGERS BIT(16)
|
||||
#define MT_QUIRK_ASUS_CUSTOM_UP BIT(17)
|
||||
#define MT_QUIRK_WIN8_PTP_BUTTONS BIT(18)
|
||||
#define MT_QUIRK_SEPARATE_APP_REPORT BIT(19)
|
||||
|
||||
#define MT_INPUTMODE_TOUCHSCREEN 0x02
|
||||
#define MT_INPUTMODE_TOUCHPAD 0x03
|
||||
|
@ -107,6 +108,7 @@ struct mt_usages {
|
|||
struct mt_application {
|
||||
struct list_head list;
|
||||
unsigned int application;
|
||||
unsigned int report_id;
|
||||
struct list_head mt_usages; /* mt usages list */
|
||||
|
||||
__s32 quirks;
|
||||
|
@ -207,6 +209,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
|
|||
#define MT_CLS_VTL 0x0110
|
||||
#define MT_CLS_GOOGLE 0x0111
|
||||
#define MT_CLS_RAZER_BLADE_STEALTH 0x0112
|
||||
#define MT_CLS_SMART_TECH 0x0113
|
||||
|
||||
#define MT_DEFAULT_MAXCONTACT 10
|
||||
#define MT_MAX_MAXCONTACT 250
|
||||
|
@ -357,6 +360,12 @@ static const struct mt_class mt_classes[] = {
|
|||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_WIN8_PTP_BUTTONS,
|
||||
},
|
||||
{ .name = MT_CLS_SMART_TECH,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_IGNORE_DUPLICATES |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_SEPARATE_APP_REPORT,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -513,8 +522,9 @@ static struct mt_usages *mt_allocate_usage(struct hid_device *hdev,
|
|||
}
|
||||
|
||||
static struct mt_application *mt_allocate_application(struct mt_device *td,
|
||||
unsigned int application)
|
||||
struct hid_report *report)
|
||||
{
|
||||
unsigned int application = report->application;
|
||||
struct mt_application *mt_application;
|
||||
|
||||
mt_application = devm_kzalloc(&td->hdev->dev, sizeof(*mt_application),
|
||||
|
@ -539,6 +549,7 @@ static struct mt_application *mt_allocate_application(struct mt_device *td,
|
|||
mt_application->scantime = DEFAULT_ZERO;
|
||||
mt_application->raw_cc = DEFAULT_ZERO;
|
||||
mt_application->quirks = td->mtclass.quirks;
|
||||
mt_application->report_id = report->id;
|
||||
|
||||
list_add_tail(&mt_application->list, &td->applications);
|
||||
|
||||
|
@ -546,19 +557,23 @@ static struct mt_application *mt_allocate_application(struct mt_device *td,
|
|||
}
|
||||
|
||||
static struct mt_application *mt_find_application(struct mt_device *td,
|
||||
unsigned int application)
|
||||
struct hid_report *report)
|
||||
{
|
||||
unsigned int application = report->application;
|
||||
struct mt_application *tmp, *mt_application = NULL;
|
||||
|
||||
list_for_each_entry(tmp, &td->applications, list) {
|
||||
if (application == tmp->application) {
|
||||
if (!(td->mtclass.quirks & MT_QUIRK_SEPARATE_APP_REPORT) ||
|
||||
tmp->report_id == report->id) {
|
||||
mt_application = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mt_application)
|
||||
mt_application = mt_allocate_application(td, application);
|
||||
mt_application = mt_allocate_application(td, report);
|
||||
|
||||
return mt_application;
|
||||
}
|
||||
|
@ -575,7 +590,7 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
|
|||
return NULL;
|
||||
|
||||
rdata->report = report;
|
||||
rdata->application = mt_find_application(td, report->application);
|
||||
rdata->application = mt_find_application(td, report);
|
||||
|
||||
if (!rdata->application) {
|
||||
devm_kfree(&td->hdev->dev, rdata);
|
||||
|
@ -1332,6 +1347,13 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
|
||||
application);
|
||||
|
||||
/*
|
||||
* some egalax touchscreens have "application == DG_TOUCHSCREEN"
|
||||
* for the stylus. Overwrite the hid_input application
|
||||
*/
|
||||
if (field->physical == HID_DG_STYLUS)
|
||||
hi->application = HID_DG_STYLUS;
|
||||
|
||||
/* let hid-core decide for the others */
|
||||
return 0;
|
||||
}
|
||||
|
@ -1520,14 +1542,12 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
|||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
char *name;
|
||||
const char *suffix = NULL;
|
||||
unsigned int application = 0;
|
||||
struct mt_report_data *rdata;
|
||||
struct mt_application *mt_application = NULL;
|
||||
struct hid_report *report;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(report, &hi->reports, hidinput_list) {
|
||||
application = report->application;
|
||||
rdata = mt_find_report_data(td, report);
|
||||
if (!rdata) {
|
||||
hid_err(hdev, "failed to allocate data for report\n");
|
||||
|
@ -1542,21 +1562,9 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
|||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* some egalax touchscreens have "application == DG_TOUCHSCREEN"
|
||||
* for the stylus. Check this first, and then rely on
|
||||
* the application field.
|
||||
*/
|
||||
if (report->field[0]->physical == HID_DG_STYLUS) {
|
||||
suffix = "Pen";
|
||||
/* force BTN_STYLUS to allow tablet matching in udev */
|
||||
__set_bit(BTN_STYLUS, hi->input->keybit);
|
||||
}
|
||||
}
|
||||
|
||||
if (!suffix) {
|
||||
switch (application) {
|
||||
switch (hi->application) {
|
||||
case HID_GD_KEYBOARD:
|
||||
case HID_GD_KEYPAD:
|
||||
case HID_GD_MOUSE:
|
||||
|
@ -1578,11 +1586,13 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
|||
case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
|
||||
suffix = "Custom Media Keys";
|
||||
break;
|
||||
case HID_DG_PEN:
|
||||
suffix = "Stylus";
|
||||
break;
|
||||
default:
|
||||
suffix = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (suffix) {
|
||||
name = devm_kzalloc(&hi->input->dev,
|
||||
|
@ -1805,6 +1815,12 @@ static const struct hid_device_id mt_devices[] = {
|
|||
USB_VENDOR_ID_LENOVO,
|
||||
USB_DEVICE_ID_LENOVO_X1_TAB) },
|
||||
|
||||
/* Lenovo X1 TAB Gen 3 */
|
||||
{ .driver_data = MT_CLS_WIN_8_DUAL,
|
||||
HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
|
||||
USB_VENDOR_ID_LENOVO,
|
||||
USB_DEVICE_ID_LENOVO_X1_TAB3) },
|
||||
|
||||
/* Anton devices */
|
||||
{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
|
||||
|
@ -2040,6 +2056,10 @@ static const struct hid_device_id mt_devices[] = {
|
|||
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
|
||||
USB_VENDOR_ID_SYNAPTICS, 0x8323) },
|
||||
|
||||
/* Smart Tech panels */
|
||||
{ .driver_data = MT_CLS_SMART_TECH,
|
||||
MT_USB_DEVICE(0x0b8c, 0x0092)},
|
||||
|
||||
/* Stantum panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
|
||||
|
|
|
@ -111,6 +111,7 @@ static const struct hid_device_id hid_quirks[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET },
|
||||
|
|
|
@ -203,9 +203,9 @@ static inline bool cdns_is_holdquirk(struct cdns_i2c *id, bool hold_wrkaround)
|
|||
*/
|
||||
static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
|
||||
{
|
||||
unsigned int isr_status, avail_bytes, updatetx;
|
||||
unsigned int isr_status, avail_bytes;
|
||||
unsigned int bytes_to_send;
|
||||
bool hold_quirk;
|
||||
bool updatetx;
|
||||
struct cdns_i2c *id = ptr;
|
||||
/* Signal completion only after everything is updated */
|
||||
int done_flag = 0;
|
||||
|
@ -224,11 +224,7 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
|
|||
* Check if transfer size register needs to be updated again for a
|
||||
* large data receive operation.
|
||||
*/
|
||||
updatetx = 0;
|
||||
if (id->recv_count > id->curr_recv_count)
|
||||
updatetx = 1;
|
||||
|
||||
hold_quirk = (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT) && updatetx;
|
||||
updatetx = id->recv_count > id->curr_recv_count;
|
||||
|
||||
/* When receiving, handle data interrupt and completion interrupt */
|
||||
if (id->p_recv_buf &&
|
||||
|
@ -251,7 +247,7 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
|
|||
id->recv_count--;
|
||||
id->curr_recv_count--;
|
||||
|
||||
if (cdns_is_holdquirk(id, hold_quirk))
|
||||
if (cdns_is_holdquirk(id, updatetx))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -262,7 +258,7 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
|
|||
* maintain transfer size non-zero while performing a large
|
||||
* receive operation.
|
||||
*/
|
||||
if (cdns_is_holdquirk(id, hold_quirk)) {
|
||||
if (cdns_is_holdquirk(id, updatetx)) {
|
||||
/* wait while fifo is full */
|
||||
while (cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET) !=
|
||||
(id->curr_recv_count - CDNS_I2C_FIFO_DEPTH))
|
||||
|
@ -284,22 +280,6 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
|
|||
CDNS_I2C_XFER_SIZE_OFFSET);
|
||||
id->curr_recv_count = id->recv_count;
|
||||
}
|
||||
} else if (id->recv_count && !hold_quirk &&
|
||||
!id->curr_recv_count) {
|
||||
|
||||
/* Set the slave address in address register*/
|
||||
cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK,
|
||||
CDNS_I2C_ADDR_OFFSET);
|
||||
|
||||
if (id->recv_count > CDNS_I2C_TRANSFER_SIZE) {
|
||||
cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE,
|
||||
CDNS_I2C_XFER_SIZE_OFFSET);
|
||||
id->curr_recv_count = CDNS_I2C_TRANSFER_SIZE;
|
||||
} else {
|
||||
cdns_i2c_writereg(id->recv_count,
|
||||
CDNS_I2C_XFER_SIZE_OFFSET);
|
||||
id->curr_recv_count = id->recv_count;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear hold (if not repeated start) and signal completion */
|
||||
|
|
|
@ -70,7 +70,6 @@ static struct or1k_pic_dev or1k_pic_level = {
|
|||
.name = "or1k-PIC-level",
|
||||
.irq_unmask = or1k_pic_unmask,
|
||||
.irq_mask = or1k_pic_mask,
|
||||
.irq_mask_ack = or1k_pic_mask_ack,
|
||||
},
|
||||
.handle = handle_level_irq,
|
||||
.flags = IRQ_LEVEL | IRQ_NOPROBE,
|
||||
|
|
|
@ -645,7 +645,7 @@ do_adb_query(struct adb_request *req)
|
|||
|
||||
switch(req->data[1]) {
|
||||
case ADB_QUERY_GETDEVINFO:
|
||||
if (req->nbytes < 3)
|
||||
if (req->nbytes < 3 || req->data[2] >= 16)
|
||||
break;
|
||||
mutex_lock(&adb_handler_mutex);
|
||||
req->reply[0] = adb_handler[req->data[2]].original_address;
|
||||
|
|
|
@ -1438,8 +1438,6 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
|
|||
M_CAN_FIFO_DATA(i / 4),
|
||||
*(u32 *)(cf->data + i));
|
||||
|
||||
can_put_echo_skb(skb, dev, 0);
|
||||
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
|
||||
cccr = m_can_read(priv, M_CAN_CCCR);
|
||||
cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT);
|
||||
|
@ -1456,6 +1454,9 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
|
|||
m_can_write(priv, M_CAN_CCCR, cccr);
|
||||
}
|
||||
m_can_write(priv, M_CAN_TXBTIE, 0x1);
|
||||
|
||||
can_put_echo_skb(skb, dev, 0);
|
||||
|
||||
m_can_write(priv, M_CAN_TXBAR, 0x1);
|
||||
/* End of xmit function for version 3.0.x */
|
||||
} else {
|
||||
|
|
|
@ -2291,7 +2291,7 @@ err:
|
|||
|
||||
/* Uses sync mcc */
|
||||
int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
|
||||
u8 page_num, u8 *data)
|
||||
u8 page_num, u32 off, u32 len, u8 *data)
|
||||
{
|
||||
struct be_dma_mem cmd;
|
||||
struct be_mcc_wrb *wrb;
|
||||
|
@ -2325,10 +2325,10 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
|
|||
req->port = cpu_to_le32(adapter->hba_port_num);
|
||||
req->page_num = cpu_to_le32(page_num);
|
||||
status = be_mcc_notify_wait(adapter);
|
||||
if (!status) {
|
||||
if (!status && len > 0) {
|
||||
struct be_cmd_resp_port_type *resp = cmd.va;
|
||||
|
||||
memcpy(data, resp->page_data, PAGE_DATA_LEN);
|
||||
memcpy(data, resp->page_data + off, len);
|
||||
}
|
||||
err:
|
||||
mutex_unlock(&adapter->mcc_lock);
|
||||
|
@ -2419,7 +2419,7 @@ int be_cmd_query_cable_type(struct be_adapter *adapter)
|
|||
int status;
|
||||
|
||||
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
|
||||
page_data);
|
||||
0, PAGE_DATA_LEN, page_data);
|
||||
if (!status) {
|
||||
switch (adapter->phy.interface_type) {
|
||||
case PHY_TYPE_QSFP:
|
||||
|
@ -2444,7 +2444,7 @@ int be_cmd_query_sfp_info(struct be_adapter *adapter)
|
|||
int status;
|
||||
|
||||
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
|
||||
page_data);
|
||||
0, PAGE_DATA_LEN, page_data);
|
||||
if (!status) {
|
||||
strlcpy(adapter->phy.vendor_name, page_data +
|
||||
SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
|
||||
|
|
|
@ -2431,7 +2431,7 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,
|
|||
int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num,
|
||||
u32 *state);
|
||||
int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
|
||||
u8 page_num, u8 *data);
|
||||
u8 page_num, u32 off, u32 len, u8 *data);
|
||||
int be_cmd_query_cable_type(struct be_adapter *adapter);
|
||||
int be_cmd_query_sfp_info(struct be_adapter *adapter);
|
||||
int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||
|
|
|
@ -1342,7 +1342,7 @@ static int be_get_module_info(struct net_device *netdev,
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
|
||||
page_data);
|
||||
0, PAGE_DATA_LEN, page_data);
|
||||
if (!status) {
|
||||
if (!page_data[SFP_PLUS_SFF_8472_COMP]) {
|
||||
modinfo->type = ETH_MODULE_SFF_8079;
|
||||
|
@ -1360,25 +1360,32 @@ static int be_get_module_eeprom(struct net_device *netdev,
|
|||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
int status;
|
||||
u32 begin, end;
|
||||
|
||||
if (!check_privilege(adapter, MAX_PRIVILEGES))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
|
||||
begin = eeprom->offset;
|
||||
end = eeprom->offset + eeprom->len;
|
||||
|
||||
if (begin < PAGE_DATA_LEN) {
|
||||
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, begin,
|
||||
min_t(u32, end, PAGE_DATA_LEN) - begin,
|
||||
data);
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
if (eeprom->offset + eeprom->len > PAGE_DATA_LEN) {
|
||||
status = be_cmd_read_port_transceiver_data(adapter,
|
||||
TR_PAGE_A2,
|
||||
data +
|
||||
PAGE_DATA_LEN);
|
||||
data += PAGE_DATA_LEN - begin;
|
||||
begin = PAGE_DATA_LEN;
|
||||
}
|
||||
|
||||
if (end > PAGE_DATA_LEN) {
|
||||
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A2,
|
||||
begin - PAGE_DATA_LEN,
|
||||
end - begin, data);
|
||||
if (status)
|
||||
goto err;
|
||||
}
|
||||
if (eeprom->offset)
|
||||
memcpy(data, data + eeprom->offset, eeprom->len);
|
||||
err:
|
||||
return be_cmd_status(status);
|
||||
}
|
||||
|
|
|
@ -1808,11 +1808,15 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
|
|||
* non-zero req_queue_pairs says that user requested a new
|
||||
* queue count via ethtool's set_channels, so use this
|
||||
* value for queues distribution across traffic classes
|
||||
* We need at least one queue pair for the interface
|
||||
* to be usable as we see in else statement.
|
||||
*/
|
||||
if (vsi->req_queue_pairs > 0)
|
||||
vsi->num_queue_pairs = vsi->req_queue_pairs;
|
||||
else if (pf->flags & I40E_FLAG_MSIX_ENABLED)
|
||||
vsi->num_queue_pairs = pf->num_lan_msix;
|
||||
else
|
||||
vsi->num_queue_pairs = 1;
|
||||
}
|
||||
|
||||
/* Number of queues per enabled TC */
|
||||
|
|
|
@ -2059,7 +2059,10 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx)
|
|||
|
||||
efx_update_sw_stats(efx, stats);
|
||||
out:
|
||||
/* releasing a DMA coherent buffer with BH disabled can panic */
|
||||
spin_unlock_bh(&efx->stats_lock);
|
||||
efx_nic_free_buffer(efx, &stats_buf);
|
||||
spin_lock_bh(&efx->stats_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -415,8 +415,9 @@ fail1:
|
|||
static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force)
|
||||
{
|
||||
struct pci_dev *dev = efx->pci_dev;
|
||||
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
||||
unsigned int vfs_assigned = pci_vfs_assigned(dev);
|
||||
int rc = 0;
|
||||
int i, rc = 0;
|
||||
|
||||
if (vfs_assigned && !force) {
|
||||
netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; "
|
||||
|
@ -424,10 +425,13 @@ static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!vfs_assigned)
|
||||
if (!vfs_assigned) {
|
||||
for (i = 0; i < efx->vf_count; i++)
|
||||
nic_data->vf[i].pci_dev = NULL;
|
||||
pci_disable_sriov(dev);
|
||||
else
|
||||
} else {
|
||||
rc = -EBUSY;
|
||||
}
|
||||
|
||||
efx_ef10_sriov_free_vf_vswitching(efx);
|
||||
efx->vf_count = 0;
|
||||
|
|
|
@ -222,6 +222,9 @@ static void dwmac4_map_mtl_dma(struct mac_device_info *hw, u32 queue, u32 chan)
|
|||
if (queue == 0 || queue == 4) {
|
||||
value &= ~MTL_RXQ_DMA_Q04MDMACH_MASK;
|
||||
value |= MTL_RXQ_DMA_Q04MDMACH(chan);
|
||||
} else if (queue > 4) {
|
||||
value &= ~MTL_RXQ_DMA_QXMDMACH_MASK(queue - 4);
|
||||
value |= MTL_RXQ_DMA_QXMDMACH(chan, queue - 4);
|
||||
} else {
|
||||
value &= ~MTL_RXQ_DMA_QXMDMACH_MASK(queue);
|
||||
value |= MTL_RXQ_DMA_QXMDMACH(chan, queue);
|
||||
|
|
|
@ -1811,7 +1811,7 @@ static int sfp_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, sfp);
|
||||
|
||||
err = devm_add_action(sfp->dev, sfp_cleanup, sfp);
|
||||
err = devm_add_action_or_reset(sfp->dev, sfp_cleanup, sfp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -453,6 +453,7 @@ static int bcm5421_init(struct mii_phy* phy)
|
|||
int can_low_power = 1;
|
||||
if (np == NULL || of_get_property(np, "no-autolowpower", NULL))
|
||||
can_low_power = 0;
|
||||
of_node_put(np);
|
||||
if (can_low_power) {
|
||||
/* Enable automatic low-power */
|
||||
sungem_phy_write(phy, 0x1c, 0x9002);
|
||||
|
|
|
@ -1974,7 +1974,7 @@ static const struct driver_info ax88179_info = {
|
|||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.stop = ax88179_stop,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
@ -1987,7 +1987,7 @@ static const struct driver_info ax88178a_info = {
|
|||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.stop = ax88179_stop,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
@ -2000,7 +2000,7 @@ static const struct driver_info cypress_GX3_info = {
|
|||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.stop = ax88179_stop,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
@ -2013,7 +2013,7 @@ static const struct driver_info dlink_dub1312_info = {
|
|||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.stop = ax88179_stop,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
@ -2026,7 +2026,7 @@ static const struct driver_info sitecom_info = {
|
|||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.stop = ax88179_stop,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
@ -2039,7 +2039,7 @@ static const struct driver_info samsung_info = {
|
|||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.stop = ax88179_stop,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
@ -2052,7 +2052,7 @@ static const struct driver_info lenovo_info = {
|
|||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.stop = ax88179_stop,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
@ -2065,7 +2065,7 @@ static const struct driver_info belkin_info = {
|
|||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.stop = ax88179_stop,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
|
|
@ -34,6 +34,7 @@ static const struct usb_device_id mt7601u_device_table[] = {
|
|||
{ USB_DEVICE(0x2717, 0x4106) },
|
||||
{ USB_DEVICE(0x2955, 0x0001) },
|
||||
{ USB_DEVICE(0x2955, 0x1001) },
|
||||
{ USB_DEVICE(0x2955, 0x1003) },
|
||||
{ USB_DEVICE(0x2a5f, 0x1000) },
|
||||
{ USB_DEVICE(0x7392, 0x7710) },
|
||||
{ 0, }
|
||||
|
|
|
@ -482,6 +482,7 @@ void xenvif_rx_action(struct xenvif_queue *queue)
|
|||
queue->rx_copy.completed = &completed_skbs;
|
||||
|
||||
while (xenvif_rx_ring_slots_available(queue) &&
|
||||
!skb_queue_empty(&queue->rx_queue) &&
|
||||
work_done < RX_BATCH_SIZE) {
|
||||
xenvif_rx_skb(queue);
|
||||
work_done++;
|
||||
|
|
|
@ -138,7 +138,9 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy,
|
|||
skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN);
|
||||
|
||||
r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len);
|
||||
if (r != frame_len) {
|
||||
if (r < 0) {
|
||||
goto fw_read_exit_free_skb;
|
||||
} else if (r != frame_len) {
|
||||
nfc_err(&client->dev,
|
||||
"Invalid frame length: %u (expected %zu)\n",
|
||||
r, frame_len);
|
||||
|
@ -182,7 +184,9 @@ static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy,
|
|||
return 0;
|
||||
|
||||
r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
|
||||
if (r != header.plen) {
|
||||
if (r < 0) {
|
||||
goto nci_read_exit_free_skb;
|
||||
} else if (r != header.plen) {
|
||||
nfc_err(&client->dev,
|
||||
"Invalid frame payload length: %u (expected %u)\n",
|
||||
r, header.plen);
|
||||
|
|
|
@ -831,6 +831,10 @@ static void hv_int_desc_free(struct hv_pci_dev *hpdev,
|
|||
u8 buffer[sizeof(struct pci_delete_interrupt)];
|
||||
} ctxt;
|
||||
|
||||
if (!int_desc->vector_count) {
|
||||
kfree(int_desc);
|
||||
return;
|
||||
}
|
||||
memset(&ctxt, 0, sizeof(ctxt));
|
||||
int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message;
|
||||
int_pkt->message_type.type =
|
||||
|
@ -893,6 +897,28 @@ static void hv_irq_mask(struct irq_data *data)
|
|||
pci_msi_mask_irq(data);
|
||||
}
|
||||
|
||||
static unsigned int hv_msi_get_int_vector(struct irq_data *data)
|
||||
{
|
||||
struct irq_cfg *cfg = irqd_cfg(data);
|
||||
|
||||
return cfg->vector;
|
||||
}
|
||||
|
||||
static int hv_msi_prepare(struct irq_domain *domain, struct device *dev,
|
||||
int nvec, msi_alloc_info_t *info)
|
||||
{
|
||||
int ret = pci_msi_prepare(domain, dev, nvec, info);
|
||||
|
||||
/*
|
||||
* By using the interrupt remapper in the hypervisor IOMMU, contiguous
|
||||
* CPU vectors is not needed for multi-MSI
|
||||
*/
|
||||
if (info->type == X86_IRQ_ALLOC_TYPE_MSI)
|
||||
info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hv_irq_unmask() - "Unmask" the IRQ by setting its current
|
||||
* affinity.
|
||||
|
@ -908,6 +934,7 @@ static void hv_irq_unmask(struct irq_data *data)
|
|||
struct msi_desc *msi_desc = irq_data_get_msi_desc(data);
|
||||
struct irq_cfg *cfg = irqd_cfg(data);
|
||||
struct retarget_msi_interrupt *params;
|
||||
struct tran_int_desc *int_desc;
|
||||
struct hv_pcibus_device *hbus;
|
||||
struct cpumask *dest;
|
||||
struct pci_bus *pbus;
|
||||
|
@ -922,6 +949,7 @@ static void hv_irq_unmask(struct irq_data *data)
|
|||
pdev = msi_desc_to_pci_dev(msi_desc);
|
||||
pbus = pdev->bus;
|
||||
hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
|
||||
int_desc = data->chip_data;
|
||||
|
||||
spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags);
|
||||
|
||||
|
@ -929,8 +957,8 @@ static void hv_irq_unmask(struct irq_data *data)
|
|||
memset(params, 0, sizeof(*params));
|
||||
params->partition_id = HV_PARTITION_ID_SELF;
|
||||
params->int_entry.source = 1; /* MSI(-X) */
|
||||
params->int_entry.address = msi_desc->msg.address_lo;
|
||||
params->int_entry.data = msi_desc->msg.data;
|
||||
params->int_entry.address = int_desc->address & 0xffffffff;
|
||||
params->int_entry.data = int_desc->data;
|
||||
params->device_id = (hbus->hdev->dev_instance.b[5] << 24) |
|
||||
(hbus->hdev->dev_instance.b[4] << 16) |
|
||||
(hbus->hdev->dev_instance.b[7] << 8) |
|
||||
|
@ -1018,12 +1046,12 @@ static void hv_pci_compose_compl(void *context, struct pci_response *resp,
|
|||
|
||||
static u32 hv_compose_msi_req_v1(
|
||||
struct pci_create_interrupt *int_pkt, struct cpumask *affinity,
|
||||
u32 slot, u8 vector)
|
||||
u32 slot, u8 vector, u8 vector_count)
|
||||
{
|
||||
int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE;
|
||||
int_pkt->wslot.slot = slot;
|
||||
int_pkt->int_desc.vector = vector;
|
||||
int_pkt->int_desc.vector_count = 1;
|
||||
int_pkt->int_desc.vector_count = vector_count;
|
||||
int_pkt->int_desc.delivery_mode = dest_Fixed;
|
||||
|
||||
/*
|
||||
|
@ -1037,14 +1065,14 @@ static u32 hv_compose_msi_req_v1(
|
|||
|
||||
static u32 hv_compose_msi_req_v2(
|
||||
struct pci_create_interrupt2 *int_pkt, struct cpumask *affinity,
|
||||
u32 slot, u8 vector)
|
||||
u32 slot, u8 vector, u8 vector_count)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE2;
|
||||
int_pkt->wslot.slot = slot;
|
||||
int_pkt->int_desc.vector = vector;
|
||||
int_pkt->int_desc.vector_count = 1;
|
||||
int_pkt->int_desc.vector_count = vector_count;
|
||||
int_pkt->int_desc.delivery_mode = dest_Fixed;
|
||||
|
||||
/*
|
||||
|
@ -1072,7 +1100,6 @@ static u32 hv_compose_msi_req_v2(
|
|||
*/
|
||||
static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
||||
{
|
||||
struct irq_cfg *cfg = irqd_cfg(data);
|
||||
struct hv_pcibus_device *hbus;
|
||||
struct hv_pci_dev *hpdev;
|
||||
struct pci_bus *pbus;
|
||||
|
@ -1081,6 +1108,8 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
|||
unsigned long flags;
|
||||
struct compose_comp_ctxt comp;
|
||||
struct tran_int_desc *int_desc;
|
||||
struct msi_desc *msi_desc;
|
||||
u8 vector, vector_count;
|
||||
struct {
|
||||
struct pci_packet pci_pkt;
|
||||
union {
|
||||
|
@ -1092,7 +1121,17 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
|||
u32 size;
|
||||
int ret;
|
||||
|
||||
pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data));
|
||||
/* Reuse the previous allocation */
|
||||
if (data->chip_data) {
|
||||
int_desc = data->chip_data;
|
||||
msg->address_hi = int_desc->address >> 32;
|
||||
msg->address_lo = int_desc->address & 0xffffffff;
|
||||
msg->data = int_desc->data;
|
||||
return;
|
||||
}
|
||||
|
||||
msi_desc = irq_data_get_msi_desc(data);
|
||||
pdev = msi_desc_to_pci_dev(msi_desc);
|
||||
dest = irq_data_get_effective_affinity_mask(data);
|
||||
pbus = pdev->bus;
|
||||
hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
|
||||
|
@ -1100,17 +1139,40 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
|||
if (!hpdev)
|
||||
goto return_null_message;
|
||||
|
||||
/* Free any previous message that might have already been composed. */
|
||||
if (data->chip_data) {
|
||||
int_desc = data->chip_data;
|
||||
data->chip_data = NULL;
|
||||
hv_int_desc_free(hpdev, int_desc);
|
||||
}
|
||||
|
||||
int_desc = kzalloc(sizeof(*int_desc), GFP_ATOMIC);
|
||||
if (!int_desc)
|
||||
goto drop_reference;
|
||||
|
||||
if (!msi_desc->msi_attrib.is_msix && msi_desc->nvec_used > 1) {
|
||||
/*
|
||||
* If this is not the first MSI of Multi MSI, we already have
|
||||
* a mapping. Can exit early.
|
||||
*/
|
||||
if (msi_desc->irq != data->irq) {
|
||||
data->chip_data = int_desc;
|
||||
int_desc->address = msi_desc->msg.address_lo |
|
||||
(u64)msi_desc->msg.address_hi << 32;
|
||||
int_desc->data = msi_desc->msg.data +
|
||||
(data->irq - msi_desc->irq);
|
||||
msg->address_hi = msi_desc->msg.address_hi;
|
||||
msg->address_lo = msi_desc->msg.address_lo;
|
||||
msg->data = int_desc->data;
|
||||
put_pcichild(hpdev);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* The vector we select here is a dummy value. The correct
|
||||
* value gets sent to the hypervisor in unmask(). This needs
|
||||
* to be aligned with the count, and also not zero. Multi-msi
|
||||
* is powers of 2 up to 32, so 32 will always work here.
|
||||
*/
|
||||
vector = 32;
|
||||
vector_count = msi_desc->nvec_used;
|
||||
} else {
|
||||
vector = hv_msi_get_int_vector(data);
|
||||
vector_count = 1;
|
||||
}
|
||||
|
||||
memset(&ctxt, 0, sizeof(ctxt));
|
||||
init_completion(&comp.comp_pkt.host_event);
|
||||
ctxt.pci_pkt.completion_func = hv_pci_compose_compl;
|
||||
|
@ -1121,14 +1183,16 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
|||
size = hv_compose_msi_req_v1(&ctxt.int_pkts.v1,
|
||||
dest,
|
||||
hpdev->desc.win_slot.slot,
|
||||
cfg->vector);
|
||||
vector,
|
||||
vector_count);
|
||||
break;
|
||||
|
||||
case PCI_PROTOCOL_VERSION_1_2:
|
||||
size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2,
|
||||
dest,
|
||||
hpdev->desc.win_slot.slot,
|
||||
cfg->vector);
|
||||
vector,
|
||||
vector_count);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1240,7 +1304,7 @@ static irq_hw_number_t hv_msi_domain_ops_get_hwirq(struct msi_domain_info *info,
|
|||
|
||||
static struct msi_domain_ops hv_msi_ops = {
|
||||
.get_hwirq = hv_msi_domain_ops_get_hwirq,
|
||||
.msi_prepare = pci_msi_prepare,
|
||||
.msi_prepare = hv_msi_prepare,
|
||||
.set_desc = pci_msi_set_desc,
|
||||
.msi_free = hv_msi_free,
|
||||
};
|
||||
|
|
|
@ -75,6 +75,7 @@ enum hp_wmi_event_ids {
|
|||
HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D,
|
||||
HPWMI_PEAKSHIFT_PERIOD = 0x0F,
|
||||
HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
|
||||
HPWMI_SANITIZATION_MODE = 0x17,
|
||||
};
|
||||
|
||||
struct bios_args {
|
||||
|
@ -631,6 +632,8 @@ static void hp_wmi_notify(u32 value, void *context)
|
|||
break;
|
||||
case HPWMI_BATTERY_CHARGE_PERIOD:
|
||||
break;
|
||||
case HPWMI_SANITIZATION_MODE:
|
||||
break;
|
||||
default:
|
||||
pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
|
||||
break;
|
||||
|
|
|
@ -150,6 +150,7 @@ static int __init versatile_reboot_probe(void)
|
|||
versatile_reboot_type = (enum versatile_reboot)reboot_id->data;
|
||||
|
||||
syscon_regmap = syscon_node_to_regmap(np);
|
||||
of_node_put(np);
|
||||
if (IS_ERR(syscon_regmap))
|
||||
return PTR_ERR(syscon_regmap);
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ static inline void
|
|||
kbd_put_queue(struct tty_port *port, int ch)
|
||||
{
|
||||
tty_insert_flip_char(port, ch, 0);
|
||||
tty_schedule_flip(port);
|
||||
tty_flip_buffer_push(port);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -64,5 +64,5 @@ kbd_puts_queue(struct tty_port *port, char *cp)
|
|||
{
|
||||
while (*cp)
|
||||
tty_insert_flip_char(port, *cp++, 0);
|
||||
tty_schedule_flip(port);
|
||||
tty_flip_buffer_push(port);
|
||||
}
|
||||
|
|
|
@ -2161,8 +2161,7 @@ out_put_budget:
|
|||
case BLK_STS_OK:
|
||||
break;
|
||||
case BLK_STS_RESOURCE:
|
||||
if (atomic_read(&sdev->device_busy) ||
|
||||
scsi_device_blocked(sdev))
|
||||
if (scsi_device_blocked(sdev))
|
||||
ret = BLK_STS_DEV_RESOURCE;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -149,6 +149,17 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool phandle_exists(const struct device_node *np,
|
||||
const char *phandle_name, int index)
|
||||
{
|
||||
struct device_node *parse_np = of_parse_phandle(np, phandle_name, index);
|
||||
|
||||
if (parse_np)
|
||||
of_node_put(parse_np);
|
||||
|
||||
return parse_np != NULL;
|
||||
}
|
||||
|
||||
#define MAX_PROP_SIZE 32
|
||||
static int ufshcd_populate_vreg(struct device *dev, const char *name,
|
||||
struct ufs_vreg **out_vreg)
|
||||
|
@ -166,7 +177,7 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name,
|
|||
}
|
||||
|
||||
snprintf(prop_name, MAX_PROP_SIZE, "%s-supply", name);
|
||||
if (!of_parse_phandle(np, prop_name, 0)) {
|
||||
if (!phandle_exists(np, prop_name, 0)) {
|
||||
dev_info(dev, "%s: Unable to find %s regulator, assuming enabled\n",
|
||||
__func__, prop_name);
|
||||
goto out;
|
||||
|
|
|
@ -267,6 +267,8 @@ static int rt2880_pinmux_pins(struct rt2880_priv *p)
|
|||
p->func[i]->pin_count,
|
||||
sizeof(int),
|
||||
GFP_KERNEL);
|
||||
if (!p->func[i]->pins)
|
||||
return -ENOMEM;
|
||||
for (j = 0; j < p->func[i]->pin_count; j++)
|
||||
p->func[i]->pins[j] = p->func[i]->pin_first + j;
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ static int spk_ttyio_receive_buf2(struct tty_struct *tty,
|
|||
}
|
||||
|
||||
if (!ldisc_data->buf_free)
|
||||
/* ttyio_in will tty_schedule_flip */
|
||||
/* ttyio_in will tty_flip_buffer_push */
|
||||
return 0;
|
||||
|
||||
/* Make sure the consumer has read buf before we have seen
|
||||
|
@ -321,7 +321,7 @@ static unsigned char ttyio_in(int timeout)
|
|||
mb();
|
||||
ldisc_data->buf_free = true;
|
||||
/* Let TTY push more characters */
|
||||
tty_schedule_flip(speakup_tty->port);
|
||||
tty_flip_buffer_push(speakup_tty->port);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -556,7 +556,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
|
|||
}
|
||||
info->idle_stats.recv_idle = jiffies;
|
||||
}
|
||||
tty_schedule_flip(port);
|
||||
tty_flip_buffer_push(port);
|
||||
|
||||
/* end of service */
|
||||
cyy_writeb(info, CyRIR, save_xir & 0x3f);
|
||||
|
@ -996,7 +996,7 @@ static void cyz_handle_rx(struct cyclades_port *info)
|
|||
mod_timer(&info->rx_full_timer, jiffies + 1);
|
||||
#endif
|
||||
info->idle_stats.recv_idle = jiffies;
|
||||
tty_schedule_flip(&info->port);
|
||||
tty_flip_buffer_push(&info->port);
|
||||
|
||||
/* Update rx_get */
|
||||
cy_writel(&buf_ctrl->rx_get, new_rx_get);
|
||||
|
@ -1172,7 +1172,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
|
|||
if (delta_count)
|
||||
wake_up_interruptible(&info->port.delta_msr_wait);
|
||||
if (special_count)
|
||||
tty_schedule_flip(&info->port);
|
||||
tty_flip_buffer_push(&info->port);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
|
|||
address = (unsigned long)(void *)buf;
|
||||
goldfish_tty_rw(qtty, address, count, 0);
|
||||
|
||||
tty_schedule_flip(&qtty->port);
|
||||
tty_flip_buffer_push(&qtty->port);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
|
@ -1393,7 +1393,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
|
|||
if (inited && !tty_throttled(tty) &&
|
||||
MoxaPortRxQueue(p) > 0) { /* RX */
|
||||
MoxaPortReadData(p);
|
||||
tty_schedule_flip(&p->port);
|
||||
tty_flip_buffer_push(&p->port);
|
||||
}
|
||||
} else {
|
||||
clear_bit(EMPTYWAIT, &p->statusflags);
|
||||
|
@ -1418,7 +1418,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
|
|||
|
||||
if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
|
||||
tty_insert_flip_char(&p->port, 0, TTY_BREAK);
|
||||
tty_schedule_flip(&p->port);
|
||||
tty_flip_buffer_push(&p->port);
|
||||
}
|
||||
|
||||
if (intr & IntrLine)
|
||||
|
|
|
@ -111,21 +111,11 @@ static void pty_unthrottle(struct tty_struct *tty)
|
|||
static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
|
||||
{
|
||||
struct tty_struct *to = tty->link;
|
||||
unsigned long flags;
|
||||
|
||||
if (tty->stopped)
|
||||
if (tty->stopped || !c)
|
||||
return 0;
|
||||
|
||||
if (c > 0) {
|
||||
spin_lock_irqsave(&to->port->lock, flags);
|
||||
/* Stuff the data into the input queue of the other end */
|
||||
c = tty_insert_flip_string(to->port, buf, c);
|
||||
spin_unlock_irqrestore(&to->port->lock, flags);
|
||||
/* And shovel */
|
||||
if (c)
|
||||
tty_flip_buffer_push(to->port);
|
||||
}
|
||||
return c;
|
||||
return tty_insert_flip_string_and_push_buffer(to->port, buf, c);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2917,8 +2917,10 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
|
|||
case UPIO_MEM32BE:
|
||||
case UPIO_MEM16:
|
||||
case UPIO_MEM:
|
||||
if (!port->mapbase)
|
||||
if (!port->mapbase) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!request_mem_region(port->mapbase, size, "serial")) {
|
||||
ret = -EBUSY;
|
||||
|
|
|
@ -1335,6 +1335,15 @@ static void pl011_stop_rx(struct uart_port *port)
|
|||
pl011_dma_rx_stop(uap);
|
||||
}
|
||||
|
||||
static void pl011_throttle_rx(struct uart_port *port)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
pl011_stop_rx(port);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static void pl011_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap =
|
||||
|
@ -1728,9 +1737,10 @@ static int pl011_allocate_irq(struct uart_amba_port *uap)
|
|||
*/
|
||||
static void pl011_enable_interrupts(struct uart_amba_port *uap)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int i;
|
||||
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
spin_lock_irqsave(&uap->port.lock, flags);
|
||||
|
||||
/* Clear out any spuriously appearing RX interrupts */
|
||||
pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
|
||||
|
@ -1752,7 +1762,14 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
|
|||
if (!pl011_dma_rx_running(uap))
|
||||
uap->im |= UART011_RXIM;
|
||||
pl011_write(uap->im, uap, REG_IMSC);
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||
}
|
||||
|
||||
static void pl011_unthrottle_rx(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port);
|
||||
|
||||
pl011_enable_interrupts(uap);
|
||||
}
|
||||
|
||||
static int pl011_startup(struct uart_port *port)
|
||||
|
@ -2127,6 +2144,8 @@ static const struct uart_ops amba_pl011_pops = {
|
|||
.stop_tx = pl011_stop_tx,
|
||||
.start_tx = pl011_start_tx,
|
||||
.stop_rx = pl011_stop_rx,
|
||||
.throttle = pl011_throttle_rx,
|
||||
.unthrottle = pl011_unthrottle_rx,
|
||||
.enable_ms = pl011_enable_ms,
|
||||
.break_ctl = pl011_break_ctl,
|
||||
.startup = pl011_startup,
|
||||
|
|
|
@ -341,7 +341,7 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
|
|||
LPC32XX_HSUART_IIR(port->membase));
|
||||
port->icount.overrun++;
|
||||
tty_insert_flip_char(tport, 0, TTY_OVERRUN);
|
||||
tty_schedule_flip(tport);
|
||||
tty_flip_buffer_push(tport);
|
||||
}
|
||||
|
||||
/* Data received? */
|
||||
|
|
|
@ -442,14 +442,14 @@ static void mvebu_uart_shutdown(struct uart_port *port)
|
|||
}
|
||||
}
|
||||
|
||||
static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
|
||||
static unsigned int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
|
||||
{
|
||||
struct mvebu_uart *mvuart = to_mvuart(port);
|
||||
unsigned int d_divisor, m_divisor;
|
||||
u32 brdv;
|
||||
|
||||
if (IS_ERR(mvuart->clk))
|
||||
return -PTR_ERR(mvuart->clk);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The baudrate is derived from the UART clock thanks to two divisors:
|
||||
|
@ -469,7 +469,7 @@ static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
|
|||
brdv |= d_divisor;
|
||||
writel(brdv, port->membase + UART_BRDV);
|
||||
|
||||
return 0;
|
||||
return DIV_ROUND_CLOSEST(port->uartclk, d_divisor * m_divisor);
|
||||
}
|
||||
|
||||
static void mvebu_uart_set_termios(struct uart_port *port,
|
||||
|
@ -506,15 +506,11 @@ static void mvebu_uart_set_termios(struct uart_port *port,
|
|||
max_baud = 230400;
|
||||
|
||||
baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud);
|
||||
if (mvebu_uart_baud_rate_set(port, baud)) {
|
||||
/* No clock available, baudrate cannot be changed */
|
||||
if (old)
|
||||
baud = uart_get_baud_rate(port, old, NULL,
|
||||
min_baud, max_baud);
|
||||
} else {
|
||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
}
|
||||
baud = mvebu_uart_baud_rate_set(port, baud);
|
||||
|
||||
/* In case baudrate cannot be changed, report previous old value */
|
||||
if (baud == 0 && old)
|
||||
baud = tty_termios_baud_rate(old);
|
||||
|
||||
/* Only the following flag changes are supported */
|
||||
if (old) {
|
||||
|
@ -525,6 +521,11 @@ static void mvebu_uart_set_termios(struct uart_port *port,
|
|||
termios->c_cflag |= CS8;
|
||||
}
|
||||
|
||||
if (baud != 0) {
|
||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -238,8 +238,7 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
|
|||
/* Enable tx dma mode */
|
||||
ucon = rd_regl(port, S3C2410_UCON);
|
||||
ucon &= ~(S3C64XX_UCON_TXBURST_MASK | S3C64XX_UCON_TXMODE_MASK);
|
||||
ucon |= (dma_get_cache_alignment() >= 16) ?
|
||||
S3C64XX_UCON_TXBURST_16 : S3C64XX_UCON_TXBURST_1;
|
||||
ucon |= S3C64XX_UCON_TXBURST_1;
|
||||
ucon |= S3C64XX_UCON_TXMODE_DMA;
|
||||
wr_regl(port, S3C2410_UCON, ucon);
|
||||
|
||||
|
@ -512,7 +511,7 @@ static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
|
|||
S3C64XX_UCON_DMASUS_EN |
|
||||
S3C64XX_UCON_TIMEOUT_EN |
|
||||
S3C64XX_UCON_RXMODE_MASK);
|
||||
ucon |= S3C64XX_UCON_RXBURST_16 |
|
||||
ucon |= S3C64XX_UCON_RXBURST_1 |
|
||||
0xf << S3C64XX_UCON_TIMEOUT_SHIFT |
|
||||
S3C64XX_UCON_EMPTYINT_EN |
|
||||
S3C64XX_UCON_TIMEOUT_EN |
|
||||
|
|
|
@ -72,6 +72,8 @@ static void stm32_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE,
|
|||
*cr3 |= USART_CR3_DEM;
|
||||
over8 = *cr1 & USART_CR1_OVER8;
|
||||
|
||||
*cr1 &= ~(USART_CR1_DEDT_MASK | USART_CR1_DEAT_MASK);
|
||||
|
||||
if (over8)
|
||||
rs485_deat_dedt = delay_ADE * baud * 8;
|
||||
else
|
||||
|
|
|
@ -389,27 +389,6 @@ int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
|
|||
}
|
||||
EXPORT_SYMBOL(__tty_insert_flip_char);
|
||||
|
||||
/**
|
||||
* tty_schedule_flip - push characters to ldisc
|
||||
* @port: tty port to push from
|
||||
*
|
||||
* Takes any pending buffers and transfers their ownership to the
|
||||
* ldisc side of the queue. It then schedules those characters for
|
||||
* processing by the line discipline.
|
||||
*/
|
||||
|
||||
void tty_schedule_flip(struct tty_port *port)
|
||||
{
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
|
||||
/* paired w/ acquire in flush_to_ldisc(); ensures
|
||||
* flush_to_ldisc() sees buffer data.
|
||||
*/
|
||||
smp_store_release(&buf->tail->commit, buf->tail->used);
|
||||
queue_work(system_unbound_wq, &buf->work);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_schedule_flip);
|
||||
|
||||
/**
|
||||
* tty_prepare_flip_string - make room for characters
|
||||
* @port: tty port
|
||||
|
@ -539,6 +518,15 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||
|
||||
}
|
||||
|
||||
static inline void tty_flip_buffer_commit(struct tty_buffer *tail)
|
||||
{
|
||||
/*
|
||||
* Paired w/ acquire in flush_to_ldisc(); ensures flush_to_ldisc() sees
|
||||
* buffer data.
|
||||
*/
|
||||
smp_store_release(&tail->commit, tail->used);
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_flip_buffer_push - terminal
|
||||
* @port: tty port to push
|
||||
|
@ -552,10 +540,44 @@ static void flush_to_ldisc(struct work_struct *work)
|
|||
|
||||
void tty_flip_buffer_push(struct tty_port *port)
|
||||
{
|
||||
tty_schedule_flip(port);
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
|
||||
tty_flip_buffer_commit(buf->tail);
|
||||
queue_work(system_unbound_wq, &buf->work);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_flip_buffer_push);
|
||||
|
||||
/**
|
||||
* tty_insert_flip_string_and_push_buffer - add characters to the tty buffer and
|
||||
* push
|
||||
* @port: tty port
|
||||
* @chars: characters
|
||||
* @size: size
|
||||
*
|
||||
* The function combines tty_insert_flip_string() and tty_flip_buffer_push()
|
||||
* with the exception of properly holding the @port->lock.
|
||||
*
|
||||
* To be used only internally (by pty currently).
|
||||
*
|
||||
* Returns: the number added.
|
||||
*/
|
||||
int tty_insert_flip_string_and_push_buffer(struct tty_port *port,
|
||||
const unsigned char *chars, size_t size)
|
||||
{
|
||||
struct tty_bufhead *buf = &port->buf;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
size = tty_insert_flip_string(port, chars, size);
|
||||
if (size)
|
||||
tty_flip_buffer_commit(buf->tail);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
queue_work(system_unbound_wq, &buf->work);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_buffer_init - prepare a tty buffer structure
|
||||
* @tty: tty to initialise
|
||||
|
|
|
@ -310,7 +310,7 @@ int kbd_rate(struct kbd_repeat *rpt)
|
|||
static void put_queue(struct vc_data *vc, int ch)
|
||||
{
|
||||
tty_insert_flip_char(&vc->port, ch, 0);
|
||||
tty_schedule_flip(&vc->port);
|
||||
tty_flip_buffer_push(&vc->port);
|
||||
}
|
||||
|
||||
static void puts_queue(struct vc_data *vc, char *cp)
|
||||
|
@ -319,7 +319,7 @@ static void puts_queue(struct vc_data *vc, char *cp)
|
|||
tty_insert_flip_char(&vc->port, *cp, 0);
|
||||
cp++;
|
||||
}
|
||||
tty_schedule_flip(&vc->port);
|
||||
tty_flip_buffer_push(&vc->port);
|
||||
}
|
||||
|
||||
static void applkey(struct vc_data *vc, int key, char mode)
|
||||
|
@ -564,7 +564,7 @@ static void fn_inc_console(struct vc_data *vc)
|
|||
static void fn_send_intr(struct vc_data *vc)
|
||||
{
|
||||
tty_insert_flip_char(&vc->port, 0, TTY_BREAK);
|
||||
tty_schedule_flip(&vc->port);
|
||||
tty_flip_buffer_push(&vc->port);
|
||||
}
|
||||
|
||||
static void fn_scroll_forw(struct vc_data *vc)
|
||||
|
|
|
@ -1838,7 +1838,7 @@ static void respond_string(const char *p, struct tty_port *port)
|
|||
tty_insert_flip_char(port, *p, 0);
|
||||
p++;
|
||||
}
|
||||
tty_schedule_flip(port);
|
||||
tty_flip_buffer_push(port);
|
||||
}
|
||||
|
||||
static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
|
||||
|
|
|
@ -4137,7 +4137,6 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
|
|||
|
||||
dwc->bh_handled_evt_cnt[dwc->irq_dbg_index] += (evt->count / 4);
|
||||
evt->count = 0;
|
||||
evt->flags &= ~DWC3_EVENT_PENDING;
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
/* Unmask interrupt */
|
||||
|
@ -4150,6 +4149,9 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
|
|||
dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval);
|
||||
}
|
||||
|
||||
/* Keep the clearing of DWC3_EVENT_PENDING at the end */
|
||||
evt->flags &= ~DWC3_EVENT_PENDING;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1013,6 +1013,9 @@ static const struct usb_device_id id_table_combined[] = {
|
|||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) },
|
||||
/* Belimo Automation devices */
|
||||
{ USB_DEVICE(FTDI_VID, BELIMO_ZTH_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, BELIMO_ZIP_PID) },
|
||||
/* ICP DAS I-756xU devices */
|
||||
{ USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) },
|
||||
{ USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) },
|
||||
|
|
|
@ -1568,6 +1568,12 @@
|
|||
#define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */
|
||||
#define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */
|
||||
|
||||
/*
|
||||
* Belimo Automation
|
||||
*/
|
||||
#define BELIMO_ZTH_PID 0x8050
|
||||
#define BELIMO_ZIP_PID 0xC811
|
||||
|
||||
/*
|
||||
* Unjo AB
|
||||
*/
|
||||
|
|
|
@ -1396,6 +1396,7 @@ void typec_set_pwr_opmode(struct typec_port *port,
|
|||
partner->usb_pd = 1;
|
||||
sysfs_notify(&partner_dev->kobj, NULL,
|
||||
"supports_usb_power_delivery");
|
||||
kobject_uevent(&partner_dev->kobj, KOBJ_CHANGE);
|
||||
}
|
||||
put_device(partner_dev);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/virtio.h>
|
||||
|
@ -508,6 +509,28 @@ static const struct virtio_config_ops virtio_mmio_config_ops = {
|
|||
.bus_name = vm_bus_name,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int virtio_mmio_freeze(struct device *dev)
|
||||
{
|
||||
struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
|
||||
|
||||
return virtio_device_freeze(&vm_dev->vdev);
|
||||
}
|
||||
|
||||
static int virtio_mmio_restore(struct device *dev)
|
||||
{
|
||||
struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (vm_dev->version == 1)
|
||||
writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
|
||||
|
||||
return virtio_device_restore(&vm_dev->vdev);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops virtio_mmio_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze, virtio_mmio_restore)
|
||||
};
|
||||
#endif
|
||||
|
||||
static void virtio_mmio_release_dev(struct device *_d)
|
||||
{
|
||||
|
@ -761,6 +784,9 @@ static struct platform_driver virtio_mmio_driver = {
|
|||
.name = "virtio-mmio",
|
||||
.of_match_table = virtio_mmio_match,
|
||||
.acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match),
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &virtio_mmio_pm_ops,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -416,7 +416,8 @@ static void __unmap_grant_pages_done(int result,
|
|||
unsigned int offset = data->unmap_ops - map->unmap_ops;
|
||||
|
||||
for (i = 0; i < data->count; i++) {
|
||||
WARN_ON(map->unmap_ops[offset+i].status);
|
||||
WARN_ON(map->unmap_ops[offset+i].status &&
|
||||
map->unmap_ops[offset+i].handle != -1);
|
||||
pr_debug("unmap handle=%d st=%d\n",
|
||||
map->unmap_ops[offset+i].handle,
|
||||
map->unmap_ops[offset+i].status);
|
||||
|
|
|
@ -4069,13 +4069,14 @@ static void send_repeat_remove(struct dlm_ls *ls, char *ms_name, int len)
|
|||
rv = _create_message(ls, sizeof(struct dlm_message) + len,
|
||||
dir_nodeid, DLM_MSG_REMOVE, &ms, &mh);
|
||||
if (rv)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
memcpy(ms->m_extra, name, len);
|
||||
ms->m_hash = hash;
|
||||
|
||||
send_message(mh, ms);
|
||||
|
||||
out:
|
||||
spin_lock(&ls->ls_remove_spin);
|
||||
ls->ls_remove_len = 0;
|
||||
memset(ls->ls_remove_name, 0, DLM_RESNAME_MAXLEN);
|
||||
|
|
|
@ -198,6 +198,9 @@ static inline int nilfs_acl_chmod(struct inode *inode)
|
|||
|
||||
static inline int nilfs_init_acl(struct inode *inode, struct inode *dir)
|
||||
{
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
return 0;
|
||||
|
||||
inode->i_mode &= ~current_umask();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -606,8 +606,12 @@ static int ntfs_attr_find(const ATTR_TYPE type, const ntfschar *name,
|
|||
a = (ATTR_RECORD*)((u8*)ctx->attr +
|
||||
le32_to_cpu(ctx->attr->length));
|
||||
for (;; a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length))) {
|
||||
if ((u8*)a < (u8*)ctx->mrec || (u8*)a > (u8*)ctx->mrec +
|
||||
le32_to_cpu(ctx->mrec->bytes_allocated))
|
||||
u8 *mrec_end = (u8 *)ctx->mrec +
|
||||
le32_to_cpu(ctx->mrec->bytes_allocated);
|
||||
u8 *name_end = (u8 *)a + le16_to_cpu(a->name_offset) +
|
||||
a->name_length * sizeof(ntfschar);
|
||||
if ((u8*)a < (u8*)ctx->mrec || (u8*)a > mrec_end ||
|
||||
name_end > mrec_end)
|
||||
break;
|
||||
ctx->attr = a;
|
||||
if (unlikely(le32_to_cpu(a->type) > le32_to_cpu(type) ||
|
||||
|
|
|
@ -12,7 +12,6 @@ extern int tty_insert_flip_string_fixed_flag(struct tty_port *port,
|
|||
extern int tty_prepare_flip_string(struct tty_port *port,
|
||||
unsigned char **chars, size_t size);
|
||||
extern void tty_flip_buffer_push(struct tty_port *port);
|
||||
void tty_schedule_flip(struct tty_port *port);
|
||||
int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag);
|
||||
|
||||
static inline int tty_insert_flip_char(struct tty_port *port,
|
||||
|
@ -40,4 +39,7 @@ static inline int tty_insert_flip_string(struct tty_port *port,
|
|||
extern void tty_buffer_lock_exclusive(struct tty_port *port);
|
||||
extern void tty_buffer_unlock_exclusive(struct tty_port *port);
|
||||
|
||||
int tty_insert_flip_string_and_push_buffer(struct tty_port *port,
|
||||
const unsigned char *chars, size_t cnt);
|
||||
|
||||
#endif /* _LINUX_TTY_FLIP_H */
|
||||
|
|
|
@ -370,6 +370,71 @@ out:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Shall not be called with lock_sock held */
|
||||
static inline struct sk_buff *bt_skb_sendmsg(struct sock *sk,
|
||||
struct msghdr *msg,
|
||||
size_t len, size_t mtu,
|
||||
size_t headroom, size_t tailroom)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
size_t size = min_t(size_t, len, mtu);
|
||||
int err;
|
||||
|
||||
skb = bt_skb_send_alloc(sk, size + headroom + tailroom,
|
||||
msg->msg_flags & MSG_DONTWAIT, &err);
|
||||
if (!skb)
|
||||
return ERR_PTR(err);
|
||||
|
||||
skb_reserve(skb, headroom);
|
||||
skb_tailroom_reserve(skb, mtu, tailroom);
|
||||
|
||||
if (!copy_from_iter_full(skb_put(skb, size), size, &msg->msg_iter)) {
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
|
||||
skb->priority = sk->sk_priority;
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
/* Similar to bt_skb_sendmsg but can split the msg into multiple fragments
|
||||
* accourding to the MTU.
|
||||
*/
|
||||
static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
|
||||
struct msghdr *msg,
|
||||
size_t len, size_t mtu,
|
||||
size_t headroom, size_t tailroom)
|
||||
{
|
||||
struct sk_buff *skb, **frag;
|
||||
|
||||
skb = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
|
||||
if (IS_ERR_OR_NULL(skb))
|
||||
return skb;
|
||||
|
||||
len -= skb->len;
|
||||
if (!len)
|
||||
return skb;
|
||||
|
||||
/* Add remaining data over MTU as continuation fragments */
|
||||
frag = &skb_shinfo(skb)->frag_list;
|
||||
while (len) {
|
||||
struct sk_buff *tmp;
|
||||
|
||||
tmp = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
|
||||
if (IS_ERR(tmp)) {
|
||||
return skb;
|
||||
}
|
||||
|
||||
len -= tmp->len;
|
||||
|
||||
*frag = tmp;
|
||||
frag = &(*frag)->next;
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
int bt_to_errno(u16 code);
|
||||
|
||||
void hci_sock_set_flag(struct sock *sk, int nr);
|
||||
|
|
|
@ -798,6 +798,7 @@ enum {
|
|||
};
|
||||
|
||||
void l2cap_chan_hold(struct l2cap_chan *c);
|
||||
struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c);
|
||||
void l2cap_chan_put(struct l2cap_chan *c);
|
||||
|
||||
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
|
||||
|
|
|
@ -111,7 +111,8 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
|
|||
|
||||
static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
if (!sk->sk_mark && sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept)
|
||||
if (!sk->sk_mark &&
|
||||
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept))
|
||||
return skb->mark;
|
||||
|
||||
return sk->sk_mark;
|
||||
|
@ -357,7 +358,7 @@ static inline bool inet_get_convert_csum(struct sock *sk)
|
|||
static inline bool inet_can_nonlocal_bind(struct net *net,
|
||||
struct inet_sock *inet)
|
||||
{
|
||||
return net->ipv4.sysctl_ip_nonlocal_bind ||
|
||||
return READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind) ||
|
||||
inet->freebind || inet->transparent;
|
||||
}
|
||||
|
||||
|
|
|
@ -346,7 +346,7 @@ void ipfrag_init(void);
|
|||
void ip_static_sysctl_init(void);
|
||||
|
||||
#define IP4_REPLY_MARK(net, mark) \
|
||||
((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0)
|
||||
(READ_ONCE((net)->ipv4.sysctl_fwmark_reflect) ? (mark) : 0)
|
||||
|
||||
static inline bool ip_is_fragment(const struct iphdr *iph)
|
||||
{
|
||||
|
@ -407,7 +407,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
|
|||
struct net *net = dev_net(dst->dev);
|
||||
unsigned int mtu;
|
||||
|
||||
if (net->ipv4.sysctl_ip_fwd_use_pmtu ||
|
||||
if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
|
||||
ip_mtu_locked(dst) ||
|
||||
!forwarding)
|
||||
return dst_mtu(dst);
|
||||
|
|
|
@ -1399,7 +1399,7 @@ void __sk_mem_reclaim(struct sock *sk, int amount);
|
|||
/* sysctl_mem values are in pages, we convert them in SK_MEM_QUANTUM units */
|
||||
static inline long sk_prot_mem_limits(const struct sock *sk, int index)
|
||||
{
|
||||
long val = sk->sk_prot->sysctl_mem[index];
|
||||
long val = READ_ONCE(sk->sk_prot->sysctl_mem[index]);
|
||||
|
||||
#if PAGE_SIZE > SK_MEM_QUANTUM
|
||||
val <<= PAGE_SHIFT - SK_MEM_QUANTUM_SHIFT;
|
||||
|
|
|
@ -1355,8 +1355,8 @@ static inline void tcp_slow_start_after_idle_check(struct sock *sk)
|
|||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
s32 delta;
|
||||
|
||||
if (!sock_net(sk)->ipv4.sysctl_tcp_slow_start_after_idle || tp->packets_out ||
|
||||
ca_ops->cong_control)
|
||||
if (!READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_slow_start_after_idle) ||
|
||||
tp->packets_out || ca_ops->cong_control)
|
||||
return;
|
||||
delta = tcp_jiffies32 - tp->lsndtime;
|
||||
if (delta > inet_csk(sk)->icsk_rto)
|
||||
|
@ -1371,7 +1371,7 @@ void tcp_select_initial_window(const struct sock *sk, int __space,
|
|||
|
||||
static inline int tcp_win_from_space(const struct sock *sk, int space)
|
||||
{
|
||||
int tcp_adv_win_scale = sock_net(sk)->ipv4.sysctl_tcp_adv_win_scale;
|
||||
int tcp_adv_win_scale = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_adv_win_scale);
|
||||
|
||||
return tcp_adv_win_scale <= 0 ?
|
||||
(space>>(-tcp_adv_win_scale)) :
|
||||
|
@ -1446,7 +1446,8 @@ static inline u32 keepalive_time_elapsed(const struct tcp_sock *tp)
|
|||
|
||||
static inline int tcp_fin_time(const struct sock *sk)
|
||||
{
|
||||
int fin_timeout = tcp_sk(sk)->linger2 ? : sock_net(sk)->ipv4.sysctl_tcp_fin_timeout;
|
||||
int fin_timeout = tcp_sk(sk)->linger2 ? :
|
||||
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fin_timeout);
|
||||
const int rto = inet_csk(sk)->icsk_rto;
|
||||
|
||||
if (fin_timeout < (rto << 2) - (rto >> 1))
|
||||
|
@ -1891,7 +1892,7 @@ void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr);
|
|||
static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp)
|
||||
{
|
||||
struct net *net = sock_net((struct sock *)tp);
|
||||
return tp->notsent_lowat ?: net->ipv4.sysctl_tcp_notsent_lowat;
|
||||
return tp->notsent_lowat ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat);
|
||||
}
|
||||
|
||||
static inline bool tcp_stream_memory_free(const struct sock *sk)
|
||||
|
|
|
@ -97,7 +97,7 @@ TRACE_EVENT(sock_exceed_buf_limit,
|
|||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, name, 32)
|
||||
__field(long *, sysctl_mem)
|
||||
__array(long, sysctl_mem, 3)
|
||||
__field(long, allocated)
|
||||
__field(int, sysctl_rmem)
|
||||
__field(int, rmem_alloc)
|
||||
|
@ -109,7 +109,9 @@ TRACE_EVENT(sock_exceed_buf_limit,
|
|||
|
||||
TP_fast_assign(
|
||||
strncpy(__entry->name, prot->name, 32);
|
||||
__entry->sysctl_mem = prot->sysctl_mem;
|
||||
__entry->sysctl_mem[0] = READ_ONCE(prot->sysctl_mem[0]);
|
||||
__entry->sysctl_mem[1] = READ_ONCE(prot->sysctl_mem[1]);
|
||||
__entry->sysctl_mem[2] = READ_ONCE(prot->sysctl_mem[2]);
|
||||
__entry->allocated = allocated;
|
||||
__entry->sysctl_rmem = sk_get_rmem0(sk, prot);
|
||||
__entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc);
|
||||
|
|
|
@ -66,11 +66,13 @@ void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, uns
|
|||
{
|
||||
u8 *ptr = NULL;
|
||||
|
||||
if (k >= SKF_NET_OFF)
|
||||
if (k >= SKF_NET_OFF) {
|
||||
ptr = skb_network_header(skb) + k - SKF_NET_OFF;
|
||||
else if (k >= SKF_LL_OFF)
|
||||
} else if (k >= SKF_LL_OFF) {
|
||||
if (unlikely(!skb_mac_header_was_set(skb)))
|
||||
return NULL;
|
||||
ptr = skb_mac_header(skb) + k - SKF_LL_OFF;
|
||||
|
||||
}
|
||||
if (ptr >= skb->head && ptr + size <= skb_tail_pointer(skb))
|
||||
return ptr;
|
||||
|
||||
|
|
|
@ -5880,10 +5880,10 @@ again:
|
|||
|
||||
if (!atomic_inc_not_zero(&event->rb->mmap_count)) {
|
||||
/*
|
||||
* Raced against perf_mmap_close() through
|
||||
* perf_event_set_output(). Try again, hope for better
|
||||
* luck.
|
||||
* Raced against perf_mmap_close(); remove the
|
||||
* event and try again.
|
||||
*/
|
||||
ring_buffer_attach(event, NULL);
|
||||
mutex_unlock(&event->mmap_mutex);
|
||||
goto again;
|
||||
}
|
||||
|
@ -10690,14 +10690,25 @@ err_size:
|
|||
goto out;
|
||||
}
|
||||
|
||||
static void mutex_lock_double(struct mutex *a, struct mutex *b)
|
||||
{
|
||||
if (b < a)
|
||||
swap(a, b);
|
||||
|
||||
mutex_lock(a);
|
||||
mutex_lock_nested(b, SINGLE_DEPTH_NESTING);
|
||||
}
|
||||
|
||||
static int
|
||||
perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
|
||||
{
|
||||
struct ring_buffer *rb = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!output_event)
|
||||
if (!output_event) {
|
||||
mutex_lock(&event->mmap_mutex);
|
||||
goto set;
|
||||
}
|
||||
|
||||
/* don't allow circular references */
|
||||
if (event == output_event)
|
||||
|
@ -10735,8 +10746,15 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
|
|||
event->pmu != output_event->pmu)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Hold both mmap_mutex to serialize against perf_mmap_close(). Since
|
||||
* output_event is already on rb->event_list, and the list iteration
|
||||
* restarts after every removal, it is guaranteed this new event is
|
||||
* observed *OR* if output_event is already removed, it's guaranteed we
|
||||
* observe !rb->mmap_count.
|
||||
*/
|
||||
mutex_lock_double(&event->mmap_mutex, &output_event->mmap_mutex);
|
||||
set:
|
||||
mutex_lock(&event->mmap_mutex);
|
||||
/* Can't redirect output if we've got an active mmap() */
|
||||
if (atomic_read(&event->mmap_count))
|
||||
goto unlock;
|
||||
|
@ -10746,6 +10764,12 @@ set:
|
|||
rb = ring_buffer_get(output_event);
|
||||
if (!rb)
|
||||
goto unlock;
|
||||
|
||||
/* did we race against perf_mmap_close() */
|
||||
if (!atomic_read(&rb->mmap_count)) {
|
||||
ring_buffer_put(rb);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
ring_buffer_attach(event, rb);
|
||||
|
@ -10753,20 +10777,13 @@ set:
|
|||
ret = 0;
|
||||
unlock:
|
||||
mutex_unlock(&event->mmap_mutex);
|
||||
if (output_event)
|
||||
mutex_unlock(&output_event->mmap_mutex);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mutex_lock_double(struct mutex *a, struct mutex *b)
|
||||
{
|
||||
if (b < a)
|
||||
swap(a, b);
|
||||
|
||||
mutex_lock(a);
|
||||
mutex_lock_nested(b, SINGLE_DEPTH_NESTING);
|
||||
}
|
||||
|
||||
static int perf_event_set_clock(struct perf_event *event, clockid_t clk_id)
|
||||
{
|
||||
bool nmi_safe = false;
|
||||
|
|
|
@ -1846,12 +1846,12 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
|
|||
bool autoreap = false;
|
||||
u64 utime, stime;
|
||||
|
||||
BUG_ON(sig == -1);
|
||||
WARN_ON_ONCE(sig == -1);
|
||||
|
||||
/* do_notify_parent_cldstop should have been called instead. */
|
||||
BUG_ON(task_is_stopped_or_traced(tsk));
|
||||
WARN_ON_ONCE(task_is_stopped_or_traced(tsk));
|
||||
|
||||
BUG_ON(!tsk->ptrace &&
|
||||
WARN_ON_ONCE(!tsk->ptrace &&
|
||||
(tsk->group_leader != tsk || !thread_group_empty(tsk)));
|
||||
|
||||
/* Wake up all pidfd waiters */
|
||||
|
|
|
@ -4266,6 +4266,8 @@ static int parse_var_defs(struct hist_trigger_data *hist_data)
|
|||
|
||||
s = kstrdup(field_str, GFP_KERNEL);
|
||||
if (!s) {
|
||||
kfree(hist_data->attrs->var_defs.name[n_vars]);
|
||||
hist_data->attrs->var_defs.name[n_vars] = NULL;
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
|
|
|
@ -348,7 +348,7 @@ static void mpol_rebind_preferred(struct mempolicy *pol,
|
|||
*/
|
||||
static void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask)
|
||||
{
|
||||
if (!pol)
|
||||
if (!pol || pol->mode == MPOL_LOCAL)
|
||||
return;
|
||||
if (!mpol_store_user_nodemask(pol) && !(pol->flags & MPOL_F_LOCAL) &&
|
||||
nodes_equal(pol->w.cpuset_mems_allowed, *newmask))
|
||||
|
|
|
@ -113,7 +113,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
|
|||
}
|
||||
|
||||
/* Find channel with given SCID.
|
||||
* Returns locked channel. */
|
||||
* Returns a reference locked channel.
|
||||
*/
|
||||
static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
|
||||
u16 cid)
|
||||
{
|
||||
|
@ -121,15 +122,19 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
|
|||
|
||||
mutex_lock(&conn->chan_lock);
|
||||
c = __l2cap_get_chan_by_scid(conn, cid);
|
||||
if (c) {
|
||||
/* Only lock if chan reference is not 0 */
|
||||
c = l2cap_chan_hold_unless_zero(c);
|
||||
if (c)
|
||||
l2cap_chan_lock(c);
|
||||
}
|
||||
mutex_unlock(&conn->chan_lock);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Find channel with given DCID.
|
||||
* Returns locked channel.
|
||||
* Returns a reference locked channel.
|
||||
*/
|
||||
static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
|
||||
u16 cid)
|
||||
|
@ -138,8 +143,12 @@ static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
|
|||
|
||||
mutex_lock(&conn->chan_lock);
|
||||
c = __l2cap_get_chan_by_dcid(conn, cid);
|
||||
if (c) {
|
||||
/* Only lock if chan reference is not 0 */
|
||||
c = l2cap_chan_hold_unless_zero(c);
|
||||
if (c)
|
||||
l2cap_chan_lock(c);
|
||||
}
|
||||
mutex_unlock(&conn->chan_lock);
|
||||
|
||||
return c;
|
||||
|
@ -164,8 +173,12 @@ static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
|
|||
|
||||
mutex_lock(&conn->chan_lock);
|
||||
c = __l2cap_get_chan_by_ident(conn, ident);
|
||||
if (c) {
|
||||
/* Only lock if chan reference is not 0 */
|
||||
c = l2cap_chan_hold_unless_zero(c);
|
||||
if (c)
|
||||
l2cap_chan_lock(c);
|
||||
}
|
||||
mutex_unlock(&conn->chan_lock);
|
||||
|
||||
return c;
|
||||
|
@ -491,6 +504,16 @@ void l2cap_chan_hold(struct l2cap_chan *c)
|
|||
kref_get(&c->kref);
|
||||
}
|
||||
|
||||
struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
|
||||
{
|
||||
BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
|
||||
|
||||
if (!kref_get_unless_zero(&c->kref))
|
||||
return NULL;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void l2cap_chan_put(struct l2cap_chan *c)
|
||||
{
|
||||
BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
|
||||
|
@ -1803,7 +1826,10 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
|
|||
src_match = !bacmp(&c->src, src);
|
||||
dst_match = !bacmp(&c->dst, dst);
|
||||
if (src_match && dst_match) {
|
||||
l2cap_chan_hold(c);
|
||||
c = l2cap_chan_hold_unless_zero(c);
|
||||
if (!c)
|
||||
continue;
|
||||
|
||||
read_unlock(&chan_list_lock);
|
||||
return c;
|
||||
}
|
||||
|
@ -1818,7 +1844,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
|
|||
}
|
||||
|
||||
if (c1)
|
||||
l2cap_chan_hold(c1);
|
||||
c1 = l2cap_chan_hold_unless_zero(c1);
|
||||
|
||||
read_unlock(&chan_list_lock);
|
||||
|
||||
|
@ -4204,6 +4230,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
|
|||
|
||||
unlock:
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -4316,6 +4343,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
|
|||
|
||||
done:
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -5044,6 +5072,7 @@ send_move_response:
|
|||
l2cap_send_move_chan_rsp(chan, result);
|
||||
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5136,6 +5165,7 @@ static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
|
|||
}
|
||||
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
}
|
||||
|
||||
static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
|
||||
|
@ -5165,6 +5195,7 @@ static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
|
|||
l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
|
||||
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
}
|
||||
|
||||
static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
|
||||
|
@ -5228,6 +5259,7 @@ static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
|
|||
l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
|
||||
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5263,6 +5295,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
|
|||
}
|
||||
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5635,12 +5668,11 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
|
|||
if (credits > max_credits) {
|
||||
BT_ERR("LE credits overflow");
|
||||
l2cap_send_disconn_req(chan, ECONNRESET);
|
||||
l2cap_chan_unlock(chan);
|
||||
|
||||
/* Return 0 so that we don't trigger an unnecessary
|
||||
* command reject packet.
|
||||
*/
|
||||
return 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
chan->tx_credits += credits;
|
||||
|
@ -5651,7 +5683,9 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
|
|||
if (chan->tx_credits)
|
||||
chan->ops->resume(chan);
|
||||
|
||||
unlock:
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6949,6 +6983,7 @@ drop:
|
|||
|
||||
done:
|
||||
l2cap_chan_unlock(chan);
|
||||
l2cap_chan_put(chan);
|
||||
}
|
||||
|
||||
static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
|
||||
|
@ -7353,7 +7388,7 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
|
|||
if (src_type != c->src_type)
|
||||
continue;
|
||||
|
||||
l2cap_chan_hold(c);
|
||||
c = l2cap_chan_hold_unless_zero(c);
|
||||
read_unlock(&chan_list_lock);
|
||||
return c;
|
||||
}
|
||||
|
|
|
@ -552,22 +552,58 @@ struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel)
|
|||
return dlc;
|
||||
}
|
||||
|
||||
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb)
|
||||
static int rfcomm_dlc_send_frag(struct rfcomm_dlc *d, struct sk_buff *frag)
|
||||
{
|
||||
int len = skb->len;
|
||||
|
||||
if (d->state != BT_CONNECTED)
|
||||
return -ENOTCONN;
|
||||
int len = frag->len;
|
||||
|
||||
BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len);
|
||||
|
||||
if (len > d->mtu)
|
||||
return -EINVAL;
|
||||
|
||||
rfcomm_make_uih(skb, d->addr);
|
||||
skb_queue_tail(&d->tx_queue, skb);
|
||||
rfcomm_make_uih(frag, d->addr);
|
||||
__skb_queue_tail(&d->tx_queue, frag);
|
||||
|
||||
if (!test_bit(RFCOMM_TX_THROTTLED, &d->flags))
|
||||
return len;
|
||||
}
|
||||
|
||||
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct sk_buff *frag, *next;
|
||||
int len;
|
||||
|
||||
if (d->state != BT_CONNECTED)
|
||||
return -ENOTCONN;
|
||||
|
||||
frag = skb_shinfo(skb)->frag_list;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
|
||||
/* Queue all fragments atomically. */
|
||||
spin_lock_irqsave(&d->tx_queue.lock, flags);
|
||||
|
||||
len = rfcomm_dlc_send_frag(d, skb);
|
||||
if (len < 0 || !frag)
|
||||
goto unlock;
|
||||
|
||||
for (; frag; frag = next) {
|
||||
int ret;
|
||||
|
||||
next = frag->next;
|
||||
|
||||
ret = rfcomm_dlc_send_frag(d, frag);
|
||||
if (ret < 0) {
|
||||
kfree_skb(frag);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
len += ret;
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&d->tx_queue.lock, flags);
|
||||
|
||||
if (len > 0 && !test_bit(RFCOMM_TX_THROTTLED, &d->flags))
|
||||
rfcomm_schedule();
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -578,47 +578,21 @@ static int rfcomm_sock_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||
lock_sock(sk);
|
||||
|
||||
sent = bt_sock_wait_ready(sk, msg->msg_flags);
|
||||
if (sent)
|
||||
goto done;
|
||||
|
||||
while (len) {
|
||||
size_t size = min_t(size_t, len, d->mtu);
|
||||
int err;
|
||||
|
||||
skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE,
|
||||
msg->msg_flags & MSG_DONTWAIT, &err);
|
||||
if (!skb) {
|
||||
if (sent == 0)
|
||||
sent = err;
|
||||
break;
|
||||
}
|
||||
skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
|
||||
|
||||
err = memcpy_from_msg(skb_put(skb, size), msg, size);
|
||||
if (err) {
|
||||
kfree_skb(skb);
|
||||
if (sent == 0)
|
||||
sent = err;
|
||||
break;
|
||||
}
|
||||
|
||||
skb->priority = sk->sk_priority;
|
||||
|
||||
err = rfcomm_dlc_send(d, skb);
|
||||
if (err < 0) {
|
||||
kfree_skb(skb);
|
||||
if (sent == 0)
|
||||
sent = err;
|
||||
break;
|
||||
}
|
||||
|
||||
sent += size;
|
||||
len -= size;
|
||||
}
|
||||
|
||||
done:
|
||||
release_sock(sk);
|
||||
|
||||
if (sent)
|
||||
return sent;
|
||||
|
||||
skb = bt_skb_sendmmsg(sk, msg, len, d->mtu, RFCOMM_SKB_HEAD_RESERVE,
|
||||
RFCOMM_SKB_TAIL_RESERVE);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
sent = rfcomm_dlc_send(d, skb);
|
||||
if (sent < 0)
|
||||
kfree_skb(skb);
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
|
|
@ -279,12 +279,10 @@ static int sco_connect(struct hci_dev *hdev, struct sock *sk)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int sco_send_frame(struct sock *sk, void *buf, int len,
|
||||
unsigned int msg_flags)
|
||||
static int sco_send_frame(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct sco_conn *conn = sco_pi(sk)->conn;
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
int len = skb->len;
|
||||
|
||||
/* Check outgoing MTU */
|
||||
if (len > conn->mtu)
|
||||
|
@ -292,11 +290,6 @@ static int sco_send_frame(struct sock *sk, void *buf, int len,
|
|||
|
||||
BT_DBG("sk %p len %d", sk, len);
|
||||
|
||||
skb = bt_skb_send_alloc(sk, len, msg_flags & MSG_DONTWAIT, &err);
|
||||
if (!skb)
|
||||
return err;
|
||||
|
||||
memcpy(skb_put(skb, len), buf, len);
|
||||
hci_send_sco(conn->hcon, skb);
|
||||
|
||||
return len;
|
||||
|
@ -715,7 +708,7 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||
size_t len)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
void *buf;
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
BT_DBG("sock %p, sk %p", sock, sk);
|
||||
|
@ -727,24 +720,21 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||
if (msg->msg_flags & MSG_OOB)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (memcpy_from_msg(buf, msg, len)) {
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
skb = bt_skb_sendmsg(sk, msg, len, len, 0, 0);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
if (sk->sk_state == BT_CONNECTED)
|
||||
err = sco_send_frame(sk, buf, len, msg->msg_flags);
|
||||
err = sco_send_frame(sk, skb);
|
||||
else
|
||||
err = -ENOTCONN;
|
||||
|
||||
release_sock(sk);
|
||||
kfree(buf);
|
||||
|
||||
if (err < 0)
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -1001,9 +1001,24 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,
|
|||
return okfn(net, sk, skb);
|
||||
|
||||
ops = nf_hook_entries_get_hook_ops(e);
|
||||
for (i = 0; i < e->num_hook_entries &&
|
||||
ops[i]->priority <= NF_BR_PRI_BRNF; i++)
|
||||
;
|
||||
for (i = 0; i < e->num_hook_entries; i++) {
|
||||
/* These hooks have already been called */
|
||||
if (ops[i]->priority < NF_BR_PRI_BRNF)
|
||||
continue;
|
||||
|
||||
/* These hooks have not been called yet, run them. */
|
||||
if (ops[i]->priority > NF_BR_PRI_BRNF)
|
||||
break;
|
||||
|
||||
/* take a closer look at NF_BR_PRI_BRNF. */
|
||||
if (ops[i]->hook == br_nf_pre_routing) {
|
||||
/* This hook diverted the skb to this function,
|
||||
* hooks after this have not been run yet.
|
||||
*/
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev,
|
||||
sk, net, okfn);
|
||||
|
|
|
@ -4570,7 +4570,6 @@ static int bpf_push_seg6_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
|
||||
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
|
||||
|
||||
return seg6_lookup_nexthop(skb, NULL, 0);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue