mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
Merge 6.1.115 into android14-6.1-lts
Changes in 6.1.115
bpf: Use raw_spinlock_t in ringbuf
iio: accel: bma400: Fix uninitialized variable field_value in tap event handling.
bpf: Make sure internal and UAPI bpf_redirect flags don't overlap
bpf: devmap: provide rxq after redirect
bpf: Fix memory leak in bpf_core_apply
RDMA/bnxt_re: Fix incorrect AVID type in WQE structure
RDMA/bnxt_re: Add a check for memory allocation
x86/resctrl: Avoid overflow in MB settings in bw_validate()
ARM: dts: bcm2837-rpi-cm3-io3: Fix HDMI hpd-gpio pin
s390/pci: Handle PCI error codes other than 0x3a
bpf: fix kfunc btf caching for modules
iio: frequency: {admv4420,adrf6780}: format Kconfig entries
iio: frequency: admv4420: fix missing select REMAP_SPI in Kconfig
drm/vmwgfx: Handle possible ENOMEM in vmw_stdu_connector_atomic_check
selftests/bpf: Fix cross-compiling urandom_read
ALSA: hda/cs8409: Fix possible NULL dereference
RDMA/cxgb4: Fix RDMA_CM_EVENT_UNREACHABLE error for iWARP
RDMA/irdma: Fix misspelling of "accept*"
RDMA/srpt: Make slab cache names unique
ipv4: give an IPv4 dev to blackhole_netdev
RDMA/bnxt_re: Return more meaningful error
RDMA/bnxt_re: Fix a bug while setting up Level-2 PBL pages
drm/msm/dpu: make sure phys resources are properly initialized
drm/msm/dsi: fix 32-bit signed integer extension in pclk_rate calculation
drm/msm: Avoid NULL dereference in msm_disp_state_print_regs()
drm/msm: Allocate memory for disp snapshot with kvzalloc()
net: usb: usbnet: fix race in probe failure
octeontx2-af: Fix potential integer overflows on integer shifts
drm/amd/amdgpu: Fix double unlock in amdgpu_mes_add_ring
macsec: don't increment counters for an unrelated SA
netdevsim: use cond_resched() in nsim_dev_trap_report_work()
net: ethernet: aeroflex: fix potential memory leak in greth_start_xmit_gbit()
net/smc: Fix searching in list of known pnetids in smc_pnet_add_pnetid
net: xilinx: axienet: fix potential memory leak in axienet_start_xmit()
net: systemport: fix potential memory leak in bcm_sysport_xmit()
irqchip/renesas-rzg2l: Align struct member names to tabs
irqchip/renesas-rzg2l: Document structure members
irqchip/renesas-rzg2l: Add support for suspend to RAM
irqchip/renesas-rzg2l: Fix missing put_device
drm/msm/dpu: Wire up DSC mask for active CTL configuration
drm/msm/dpu: don't always program merge_3d block
tcp/dccp: Don't use timer_pending() in reqsk_queue_unlink().
genetlink: hold RCU in genlmsg_mcast()
ravb: Remove setting of RX software timestamp
net: ravb: Only advertise Rx/Tx timestamps if hardware supports it
scsi: target: core: Fix null-ptr-deref in target_alloc_device()
smb: client: fix OOBs when building SMB2_IOCTL request
usb: typec: altmode should keep reference to parent
s390: Initialize psw mask in perf_arch_fetch_caller_regs()
Bluetooth: bnep: fix wild-memory-access in proto_unregister
net/mlx5: Remove redundant cmdif revision check
net/mlx5: split mlx5_cmd_init() to probe and reload routines
net/mlx5: Fix command bitmask initialization
net/mlx5: Unregister notifier on eswitch init failure
riscv, bpf: Make BPF_CMPXCHG fully ordered
bpf: Fix iter/task tid filtering
arm64:uprobe fix the uprobe SWBP_INSN in big-endian
arm64: probes: Fix uprobes for big-endian kernels
xhci: dbgtty: remove kfifo_out() wrapper
xhci: dbgtty: use kfifo from tty_port struct
xhci: dbc: honor usb transfer size boundaries.
usb: gadget: f_uac2: Replace snprintf() with the safer scnprintf() variant
usb: gadget: f_uac2: fix non-newline-terminated function name
usb: gadget: f_uac2: fix return value for UAC2_ATTRIBUTE_STRING store
usb: gadget: Add function wakeup support
XHCI: Separate PORT and CAPs macros into dedicated file
usb: dwc3: core: Fix system suspend on TI AM62 platforms
tty/serial: Make ->dcd_change()+uart_handle_dcd_change() status bool active
serial: Make uart_handle_cts_change() status param bool active
serial: imx: Update mctrl old_status on RTSD interrupt
block, bfq: fix procress reference leakage for bfqq in merge chain
exec: don't WARN for racy path_noexec check
fs/ntfs3: Add more attributes checks in mi_enum_attr()
drm/vboxvideo: Replace fake VLA at end of vbva_mouse_pointer_shape with real VLA
ASoC: codecs: lpass-rx-macro: add missing CDC_RX_BCL_VBAT_RF_PROC2 to default regs values
ASoC: fsl_sai: Enable 'FIFO continue on error' FCONT bit
arm64: Force position-independent veneers
udf: refactor udf_current_aext() to handle error
udf: fix uninit-value use in udf_get_fileshortad
ASoC: qcom: sm8250: add qrb4210-rb2-sndcard compatible string
platform/x86: dell-sysman: add support for alienware products
LoongArch: Add support to clone a time namespace
LoongArch: Don't crash in stack_top() for tasks without vDSO
jfs: Fix sanity check in dbMount
tracing: Consider the NULL character when validating the event length
xfrm: extract dst lookup parameters into a struct
xfrm: respect ip protocols rules criteria when performing dst lookups
net/sun3_82586: fix potential memory leak in sun3_82586_send_packet()
be2net: fix potential memory leak in be_xmit()
net: plip: fix break; causing plip to never transmit
octeon_ep: Implement helper for iterating packets in Rx queue
octeon_ep: Add SKB allocation failures handling in __octep_oq_process_rx()
net: dsa: mv88e6xxx: Fix error when setting port policy on mv88e6393x
netfilter: xtables: fix typo causing some targets not to load on IPv6
net: wwan: fix global oob in wwan_rtnl_policy
docs: net: reformat driver.rst from a list to sections
net: provide macros for commonly copied lockless queue stop/wake code
net/sched: adjust device watchdog timer to detect stopped queue at right time
net: fix races in netdev_tx_sent_queue()/dev_watchdog()
net: usb: usbnet: fix name regression
net/sched: act_api: deny mismatched skip_sw/skip_hw flags for actions created by classifiers
net: sched: fix use-after-free in taprio_change()
r8169: avoid unsolicited interrupts
posix-clock: posix-clock: Fix unbalanced locking in pc_clock_settime()
Bluetooth: SCO: Fix UAF on sco_sock_timeout
Bluetooth: ISO: Fix UAF on iso_sock_timeout
bpf,perf: Fix perf_event_detach_bpf_prog error handling
ASoC: dt-bindings: davinci-mcasp: Fix interrupts property
ASoC: dt-bindings: davinci-mcasp: Fix interrupt properties
ALSA: firewire-lib: Avoid division by zero in apply_constraint_to_size()
powercap: dtpm_devfreq: Fix error check against dev_pm_qos_add_request()
ALSA: hda/realtek: Update default depop procedure
cpufreq/cppc: Move and rename cppc_cpufreq_{perf_to_khz|khz_to_perf}()
cpufreq: CPPC: fix perf_to_khz/khz_to_perf conversion exception
btrfs: fix passing 0 to ERR_PTR in btrfs_search_dir_index_item()
btrfs: zoned: fix zone unusable accounting for freed reserved extent
drm/amd: Guard against bad data for ATIF ACPI method
ACPI: resource: Add LG 16T90SP to irq1_level_low_skip_override[]
ACPI: PRM: Find EFI_MEMORY_RUNTIME block for PRM handler and context
ACPI: button: Add DMI quirk for Samsung Galaxy Book2 to fix initial lid detection issue
nilfs2: fix kernel bug due to missing clearing of buffer delay flag
openat2: explicitly return -E2BIG for (usize > PAGE_SIZE)
KVM: nSVM: Ignore nCR3[4:0] when loading PDPTEs from memory
KVM: arm64: Don't eagerly teardown the vgic on init error
ALSA: hda/realtek: Add subwoofer quirk for Acer Predator G9-593
LoongArch: Get correct cores_per_package for SMT systems
xfrm: fix one more kernel-infoleak in algo dumping
hv_netvsc: Fix VF namespace also in synthetic NIC NETDEV_REGISTER event
drm/amd/display: Disable PSR-SU on Parade 08-01 TCON too
selinux: improve error checking in sel_write_load()
serial: protect uart_port_dtr_rts() in uart_shutdown() too
net: phy: dp83822: Fix reset pin definitions
ASoC: qcom: Fix NULL Dereference in asoc_qcom_lpass_cpu_platform_probe()
platform/x86: dell-wmi: Ignore suspend notifications
ACPI: PRM: Clean up guid type in struct prm_handler_info
arm64/uprobes: change the uprobe_opcode_t typedef to fix the sparse warning
xfrm: validate new SA's prefixlen using SA family when sel.family is unset
Linux 6.1.115
Change-Id: I3348b13afe931340f904062b8a22d8d6c4a46d5c
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -102,21 +102,21 @@ properties:
|
||||
default: 2
|
||||
|
||||
interrupts:
|
||||
anyOf:
|
||||
- minItems: 1
|
||||
items:
|
||||
- description: TX interrupt
|
||||
- description: RX interrupt
|
||||
- items:
|
||||
- description: common/combined interrupt
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
oneOf:
|
||||
- minItems: 1
|
||||
- description: TX interrupt
|
||||
const: tx
|
||||
- description: RX interrupt
|
||||
const: rx
|
||||
- description: TX and RX interrupts
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
- const: common
|
||||
- description: Common/combined interrupt
|
||||
const: common
|
||||
|
||||
fck_parent:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
|
||||
@@ -4,15 +4,19 @@
|
||||
Softnet Driver Issues
|
||||
=====================
|
||||
|
||||
Transmit path guidelines:
|
||||
Transmit path guidelines
|
||||
========================
|
||||
|
||||
1) The ndo_start_xmit method must not return NETDEV_TX_BUSY under
|
||||
any normal circumstances. It is considered a hard error unless
|
||||
there is no way your device can tell ahead of time when its
|
||||
transmit function will become busy.
|
||||
Stop queues in advance
|
||||
----------------------
|
||||
|
||||
Instead it must maintain the queue properly. For example,
|
||||
for a driver implementing scatter-gather this means::
|
||||
The ndo_start_xmit method must not return NETDEV_TX_BUSY under
|
||||
any normal circumstances. It is considered a hard error unless
|
||||
there is no way your device can tell ahead of time when its
|
||||
transmit function will become busy.
|
||||
|
||||
Instead it must maintain the queue properly. For example,
|
||||
for a driver implementing scatter-gather this means::
|
||||
|
||||
static netdev_tx_t drv_hard_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
@@ -42,56 +46,79 @@ Transmit path guidelines:
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
And then at the end of your TX reclamation event handling::
|
||||
And then at the end of your TX reclamation event handling::
|
||||
|
||||
if (netif_queue_stopped(dp->dev) &&
|
||||
TX_BUFFS_AVAIL(dp) > (MAX_SKB_FRAGS + 1))
|
||||
netif_wake_queue(dp->dev);
|
||||
|
||||
For a non-scatter-gather supporting card, the three tests simply become::
|
||||
For a non-scatter-gather supporting card, the three tests simply become::
|
||||
|
||||
/* This is a hard error log it. */
|
||||
if (TX_BUFFS_AVAIL(dp) <= 0)
|
||||
|
||||
and::
|
||||
and::
|
||||
|
||||
if (TX_BUFFS_AVAIL(dp) == 0)
|
||||
|
||||
and::
|
||||
and::
|
||||
|
||||
if (netif_queue_stopped(dp->dev) &&
|
||||
TX_BUFFS_AVAIL(dp) > 0)
|
||||
netif_wake_queue(dp->dev);
|
||||
|
||||
2) An ndo_start_xmit method must not modify the shared parts of a
|
||||
cloned SKB.
|
||||
Lockless queue stop / wake helper macros
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
3) Do not forget that once you return NETDEV_TX_OK from your
|
||||
ndo_start_xmit method, it is your driver's responsibility to free
|
||||
up the SKB and in some finite amount of time.
|
||||
.. kernel-doc:: include/net/netdev_queues.h
|
||||
:doc: Lockless queue stopping / waking helpers.
|
||||
|
||||
For example, this means that it is not allowed for your TX
|
||||
mitigation scheme to let TX packets "hang out" in the TX
|
||||
ring unreclaimed forever if no new TX packets are sent.
|
||||
This error can deadlock sockets waiting for send buffer room
|
||||
to be freed up.
|
||||
No exclusive ownership
|
||||
----------------------
|
||||
|
||||
If you return NETDEV_TX_BUSY from the ndo_start_xmit method, you
|
||||
must not keep any reference to that SKB and you must not attempt
|
||||
to free it up.
|
||||
An ndo_start_xmit method must not modify the shared parts of a
|
||||
cloned SKB.
|
||||
|
||||
Probing guidelines:
|
||||
Timely completions
|
||||
------------------
|
||||
|
||||
1) Any hardware layer address you obtain for your device should
|
||||
be verified. For example, for ethernet check it with
|
||||
linux/etherdevice.h:is_valid_ether_addr()
|
||||
Do not forget that once you return NETDEV_TX_OK from your
|
||||
ndo_start_xmit method, it is your driver's responsibility to free
|
||||
up the SKB and in some finite amount of time.
|
||||
|
||||
Close/stop guidelines:
|
||||
For example, this means that it is not allowed for your TX
|
||||
mitigation scheme to let TX packets "hang out" in the TX
|
||||
ring unreclaimed forever if no new TX packets are sent.
|
||||
This error can deadlock sockets waiting for send buffer room
|
||||
to be freed up.
|
||||
|
||||
1) After the ndo_stop routine has been called, the hardware must
|
||||
not receive or transmit any data. All in flight packets must
|
||||
be aborted. If necessary, poll or wait for completion of
|
||||
any reset commands.
|
||||
If you return NETDEV_TX_BUSY from the ndo_start_xmit method, you
|
||||
must not keep any reference to that SKB and you must not attempt
|
||||
to free it up.
|
||||
|
||||
2) The ndo_stop routine will be called by unregister_netdevice
|
||||
if device is still UP.
|
||||
Probing guidelines
|
||||
==================
|
||||
|
||||
Address validation
|
||||
------------------
|
||||
|
||||
Any hardware layer address you obtain for your device should
|
||||
be verified. For example, for ethernet check it with
|
||||
linux/etherdevice.h:is_valid_ether_addr()
|
||||
|
||||
Close/stop guidelines
|
||||
=====================
|
||||
|
||||
Quiescence
|
||||
----------
|
||||
|
||||
After the ndo_stop routine has been called, the hardware must
|
||||
not receive or transmit any data. All in flight packets must
|
||||
be aborted. If necessary, poll or wait for completion of
|
||||
any reset commands.
|
||||
|
||||
Auto-close
|
||||
----------
|
||||
|
||||
The ndo_stop routine will be called by unregister_netdevice
|
||||
if device is still UP.
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 114
|
||||
SUBLEVEL = 115
|
||||
EXTRAVERSION =
|
||||
NAME = Curry Ramen
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
hpd-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
|
||||
hpd-gpios = <&expgpio 0 GPIO_ACTIVE_LOW>;
|
||||
power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# Copyright (C) 1995-2001 by Russell King
|
||||
|
||||
LDFLAGS_vmlinux :=--no-undefined -X
|
||||
LDFLAGS_vmlinux :=--no-undefined -X --pic-veneer
|
||||
|
||||
ifeq ($(CONFIG_RELOCATABLE), y)
|
||||
# Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour
|
||||
|
||||
@@ -10,21 +10,19 @@
|
||||
#include <asm/insn.h>
|
||||
#include <asm/probes.h>
|
||||
|
||||
#define MAX_UINSN_BYTES AARCH64_INSN_SIZE
|
||||
|
||||
#define UPROBE_SWBP_INSN BRK64_OPCODE_UPROBES
|
||||
#define UPROBE_SWBP_INSN cpu_to_le32(BRK64_OPCODE_UPROBES)
|
||||
#define UPROBE_SWBP_INSN_SIZE AARCH64_INSN_SIZE
|
||||
#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES
|
||||
#define UPROBE_XOL_SLOT_BYTES AARCH64_INSN_SIZE
|
||||
|
||||
typedef u32 uprobe_opcode_t;
|
||||
typedef __le32 uprobe_opcode_t;
|
||||
|
||||
struct arch_uprobe_task {
|
||||
};
|
||||
|
||||
struct arch_uprobe {
|
||||
union {
|
||||
u8 insn[MAX_UINSN_BYTES];
|
||||
u8 ixol[MAX_UINSN_BYTES];
|
||||
__le32 insn;
|
||||
__le32 ixol;
|
||||
};
|
||||
struct arch_probe_insn api;
|
||||
bool simulate;
|
||||
|
||||
@@ -42,7 +42,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
|
||||
else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE))
|
||||
return -EINVAL;
|
||||
|
||||
insn = *(probe_opcode_t *)(&auprobe->insn[0]);
|
||||
insn = le32_to_cpu(auprobe->insn);
|
||||
|
||||
switch (arm_probe_decode_insn(insn, &auprobe->api)) {
|
||||
case INSN_REJECTED:
|
||||
@@ -108,7 +108,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
if (!auprobe->simulate)
|
||||
return false;
|
||||
|
||||
insn = *(probe_opcode_t *)(&auprobe->insn[0]);
|
||||
insn = le32_to_cpu(auprobe->insn);
|
||||
addr = instruction_pointer(regs);
|
||||
|
||||
if (auprobe->api.handler)
|
||||
|
||||
@@ -877,6 +877,9 @@ static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
|
||||
static int check_vcpu_requests(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (kvm_request_pending(vcpu)) {
|
||||
if (kvm_check_request(KVM_REQ_VM_DEAD, vcpu))
|
||||
return -EIO;
|
||||
|
||||
if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
|
||||
kvm_vcpu_sleep(vcpu);
|
||||
|
||||
|
||||
@@ -494,10 +494,10 @@ int kvm_vgic_map_resources(struct kvm *kvm)
|
||||
out:
|
||||
mutex_unlock(&kvm->arch.config_lock);
|
||||
out_slots:
|
||||
mutex_unlock(&kvm->slots_lock);
|
||||
|
||||
if (ret)
|
||||
kvm_vgic_destroy(kvm);
|
||||
kvm_vm_dead(kvm);
|
||||
|
||||
mutex_unlock(&kvm->slots_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ config LOONGARCH
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_VDSO_TIME_NS
|
||||
select GPIOLIB
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_MMAP_RND_BITS if MMU
|
||||
|
||||
@@ -25,6 +25,10 @@ struct loongson_board_info {
|
||||
const char *board_vendor;
|
||||
};
|
||||
|
||||
/*
|
||||
* The "core" of cores_per_node and cores_per_package stands for a
|
||||
* logical core, which means in a SMT system it stands for a thread.
|
||||
*/
|
||||
struct loongson_system_configuration {
|
||||
int nr_cpus;
|
||||
int nr_nodes;
|
||||
|
||||
@@ -81,6 +81,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
|
||||
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
|
||||
|
||||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
|
||||
|
||||
#ifdef CONFIG_FLATMEM
|
||||
|
||||
|
||||
@@ -91,9 +91,16 @@ static inline bool loongarch_vdso_hres_capable(void)
|
||||
|
||||
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
|
||||
{
|
||||
return get_vdso_data();
|
||||
return (const struct vdso_data *)get_vdso_data();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TIME_NS
|
||||
static __always_inline
|
||||
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
|
||||
{
|
||||
return (const struct vdso_data *)(get_vdso_data() + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE);
|
||||
}
|
||||
#endif
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
|
||||
|
||||
@@ -16,10 +16,33 @@ struct vdso_pcpu_data {
|
||||
|
||||
struct loongarch_vdso_data {
|
||||
struct vdso_pcpu_data pdata[NR_CPUS];
|
||||
struct vdso_data data[CS_BASES]; /* Arch-independent data */
|
||||
};
|
||||
|
||||
#define VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data))
|
||||
/*
|
||||
* The layout of vvar:
|
||||
*
|
||||
* high
|
||||
* +---------------------+--------------------------+
|
||||
* | loongarch vdso data | LOONGARCH_VDSO_DATA_SIZE |
|
||||
* +---------------------+--------------------------+
|
||||
* | time-ns vdso data | PAGE_SIZE |
|
||||
* +---------------------+--------------------------+
|
||||
* | generic vdso data | PAGE_SIZE |
|
||||
* +---------------------+--------------------------+
|
||||
* low
|
||||
*/
|
||||
#define LOONGARCH_VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data))
|
||||
#define LOONGARCH_VDSO_DATA_PAGES (LOONGARCH_VDSO_DATA_SIZE >> PAGE_SHIFT)
|
||||
|
||||
enum vvar_pages {
|
||||
VVAR_GENERIC_PAGE_OFFSET,
|
||||
VVAR_TIMENS_PAGE_OFFSET,
|
||||
VVAR_LOONGARCH_PAGES_START,
|
||||
VVAR_LOONGARCH_PAGES_END = VVAR_LOONGARCH_PAGES_START + LOONGARCH_VDSO_DATA_PAGES - 1,
|
||||
VVAR_NR_PAGES,
|
||||
};
|
||||
|
||||
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
|
||||
|
||||
static inline unsigned long get_vdso_base(void)
|
||||
{
|
||||
@@ -34,10 +57,9 @@ static inline unsigned long get_vdso_base(void)
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline const struct vdso_data *get_vdso_data(void)
|
||||
static inline unsigned long get_vdso_data(void)
|
||||
{
|
||||
return (const struct vdso_data *)(get_vdso_base()
|
||||
- VDSO_DATA_SIZE + SMP_CACHE_BYTES * NR_CPUS);
|
||||
return get_vdso_base() - VVAR_SIZE;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@@ -271,13 +271,15 @@ unsigned long stack_top(void)
|
||||
{
|
||||
unsigned long top = TASK_SIZE & PAGE_MASK;
|
||||
|
||||
/* Space for the VDSO & data page */
|
||||
top -= PAGE_ALIGN(current->thread.vdso->size);
|
||||
top -= PAGE_SIZE;
|
||||
if (current->thread.vdso) {
|
||||
/* Space for the VDSO & data page */
|
||||
top -= PAGE_ALIGN(current->thread.vdso->size);
|
||||
top -= VVAR_SIZE;
|
||||
|
||||
/* Space to randomize the VDSO base */
|
||||
if (current->flags & PF_RANDOMIZE)
|
||||
top -= VDSO_RANDOMIZE_SIZE;
|
||||
/* Space to randomize the VDSO base */
|
||||
if (current->flags & PF_RANDOMIZE)
|
||||
top -= VDSO_RANDOMIZE_SIZE;
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#define SMBIOS_FREQHIGH_OFFSET 0x17
|
||||
#define SMBIOS_FREQLOW_MASK 0xFF
|
||||
#define SMBIOS_CORE_PACKAGE_OFFSET 0x23
|
||||
#define SMBIOS_THREAD_PACKAGE_OFFSET 0x25
|
||||
#define LOONGSON_EFI_ENABLE (1 << 3)
|
||||
|
||||
struct screen_info screen_info __section(".data");
|
||||
@@ -115,7 +116,7 @@ static void __init parse_cpu_table(const struct dmi_header *dm)
|
||||
cpu_clock_freq = freq_temp * 1000000;
|
||||
|
||||
loongson_sysconf.cpuname = (void *)dmi_string_parse(dm, dmi_data[16]);
|
||||
loongson_sysconf.cores_per_package = *(dmi_data + SMBIOS_CORE_PACKAGE_OFFSET);
|
||||
loongson_sysconf.cores_per_package = *(dmi_data + SMBIOS_THREAD_PACKAGE_OFFSET);
|
||||
|
||||
pr_info("CpuClock = %llu\n", cpu_clock_freq);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time_namespace.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
@@ -26,12 +27,17 @@ extern char vdso_start[], vdso_end[];
|
||||
|
||||
/* Kernel-provided data used by the VDSO. */
|
||||
static union {
|
||||
u8 page[VDSO_DATA_SIZE];
|
||||
u8 page[PAGE_SIZE];
|
||||
struct vdso_data data[CS_BASES];
|
||||
} generic_vdso_data __page_aligned_data;
|
||||
|
||||
static union {
|
||||
u8 page[LOONGARCH_VDSO_DATA_SIZE];
|
||||
struct loongarch_vdso_data vdata;
|
||||
} loongarch_vdso_data __page_aligned_data;
|
||||
|
||||
static struct page *vdso_pages[] = { NULL };
|
||||
struct vdso_data *vdso_data = loongarch_vdso_data.vdata.data;
|
||||
struct vdso_data *vdso_data = generic_vdso_data.data;
|
||||
struct vdso_pcpu_data *vdso_pdata = loongarch_vdso_data.vdata.pdata;
|
||||
|
||||
static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma)
|
||||
@@ -41,6 +47,43 @@ static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
|
||||
struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
unsigned long pfn;
|
||||
struct page *timens_page = find_timens_vvar_page(vma);
|
||||
|
||||
switch (vmf->pgoff) {
|
||||
case VVAR_GENERIC_PAGE_OFFSET:
|
||||
if (!timens_page)
|
||||
pfn = sym_to_pfn(vdso_data);
|
||||
else
|
||||
pfn = page_to_pfn(timens_page);
|
||||
break;
|
||||
#ifdef CONFIG_TIME_NS
|
||||
case VVAR_TIMENS_PAGE_OFFSET:
|
||||
/*
|
||||
* If a task belongs to a time namespace then a namespace specific
|
||||
* VVAR is mapped with the VVAR_GENERIC_PAGE_OFFSET and the real
|
||||
* VVAR page is mapped with the VVAR_TIMENS_PAGE_OFFSET offset.
|
||||
* See also the comment near timens_setup_vdso_data().
|
||||
*/
|
||||
if (!timens_page)
|
||||
return VM_FAULT_SIGBUS;
|
||||
else
|
||||
pfn = sym_to_pfn(vdso_data);
|
||||
break;
|
||||
#endif /* CONFIG_TIME_NS */
|
||||
case VVAR_LOONGARCH_PAGES_START ... VVAR_LOONGARCH_PAGES_END:
|
||||
pfn = sym_to_pfn(&loongarch_vdso_data) + vmf->pgoff - VVAR_LOONGARCH_PAGES_START;
|
||||
break;
|
||||
default:
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
return vmf_insert_pfn(vma, vmf->address, pfn);
|
||||
}
|
||||
|
||||
struct loongarch_vdso_info vdso_info = {
|
||||
.vdso = vdso_start,
|
||||
.size = PAGE_SIZE,
|
||||
@@ -51,6 +94,7 @@ struct loongarch_vdso_info vdso_info = {
|
||||
},
|
||||
.data_mapping = {
|
||||
.name = "[vvar]",
|
||||
.fault = vvar_fault,
|
||||
},
|
||||
.offset_sigreturn = vdso_offset_sigreturn,
|
||||
};
|
||||
@@ -73,6 +117,37 @@ static int __init init_vdso(void)
|
||||
}
|
||||
subsys_initcall(init_vdso);
|
||||
|
||||
#ifdef CONFIG_TIME_NS
|
||||
struct vdso_data *arch_get_vdso_data(void *vvar_page)
|
||||
{
|
||||
return (struct vdso_data *)(vvar_page);
|
||||
}
|
||||
|
||||
/*
|
||||
* The vvar mapping contains data for a specific time namespace, so when a
|
||||
* task changes namespace we must unmap its vvar data for the old namespace.
|
||||
* Subsequent faults will map in data for the new namespace.
|
||||
*
|
||||
* For more details see timens_setup_vdso_data().
|
||||
*/
|
||||
int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
|
||||
{
|
||||
struct mm_struct *mm = task->mm;
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
VMA_ITERATOR(vmi, mm, 0);
|
||||
|
||||
mmap_read_lock(mm);
|
||||
for_each_vma(vmi, vma) {
|
||||
if (vma_is_special_mapping(vma, &vdso_info.data_mapping))
|
||||
zap_vma_pages(vma);
|
||||
}
|
||||
mmap_read_unlock(mm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned long vdso_base(void)
|
||||
{
|
||||
unsigned long base = STACK_TOP;
|
||||
@@ -88,7 +163,7 @@ static unsigned long vdso_base(void)
|
||||
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||
{
|
||||
int ret;
|
||||
unsigned long vvar_size, size, data_addr, vdso_addr;
|
||||
unsigned long size, data_addr, vdso_addr;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
struct loongarch_vdso_info *info = current->thread.vdso;
|
||||
@@ -100,32 +175,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||
* Determine total area size. This includes the VDSO data itself
|
||||
* and the data pages.
|
||||
*/
|
||||
vvar_size = VDSO_DATA_SIZE;
|
||||
size = vvar_size + info->size;
|
||||
size = VVAR_SIZE + info->size;
|
||||
|
||||
data_addr = get_unmapped_area(NULL, vdso_base(), size, 0, 0);
|
||||
if (IS_ERR_VALUE(data_addr)) {
|
||||
ret = data_addr;
|
||||
goto out;
|
||||
}
|
||||
vdso_addr = data_addr + VDSO_DATA_SIZE;
|
||||
|
||||
vma = _install_special_mapping(mm, data_addr, vvar_size,
|
||||
VM_READ | VM_MAYREAD,
|
||||
vma = _install_special_mapping(mm, data_addr, VVAR_SIZE,
|
||||
VM_READ | VM_MAYREAD | VM_PFNMAP,
|
||||
&info->data_mapping);
|
||||
if (IS_ERR(vma)) {
|
||||
ret = PTR_ERR(vma);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Map VDSO data page. */
|
||||
ret = remap_pfn_range(vma, data_addr,
|
||||
virt_to_phys(&loongarch_vdso_data) >> PAGE_SHIFT,
|
||||
vvar_size, PAGE_READONLY);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Map VDSO code page. */
|
||||
vdso_addr = data_addr + VVAR_SIZE;
|
||||
vma = _install_special_mapping(mm, vdso_addr, info->size,
|
||||
VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
|
||||
&info->code_mapping);
|
||||
|
||||
@@ -21,7 +21,7 @@ static __always_inline int read_cpu_id(void)
|
||||
|
||||
static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
|
||||
{
|
||||
return (struct vdso_pcpu_data *)(get_vdso_base() - VDSO_DATA_SIZE);
|
||||
return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE);
|
||||
}
|
||||
|
||||
extern
|
||||
|
||||
@@ -542,8 +542,8 @@ static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
|
||||
rv_lr_w(r0, 0, rd, 0, 0), ctx);
|
||||
jmp_offset = ninsns_rvoff(8);
|
||||
emit(rv_bne(RV_REG_T2, r0, jmp_offset >> 1), ctx);
|
||||
emit(is64 ? rv_sc_d(RV_REG_T3, rs, rd, 0, 0) :
|
||||
rv_sc_w(RV_REG_T3, rs, rd, 0, 0), ctx);
|
||||
emit(is64 ? rv_sc_d(RV_REG_T3, rs, rd, 0, 1) :
|
||||
rv_sc_w(RV_REG_T3, rs, rd, 0, 1), ctx);
|
||||
jmp_offset = ninsns_rvoff(-6);
|
||||
emit(rv_bne(RV_REG_T3, 0, jmp_offset >> 1), ctx);
|
||||
emit(rv_fence(0x3, 0x3), ctx);
|
||||
|
||||
@@ -75,6 +75,7 @@ struct perf_sf_sde_regs {
|
||||
#define SAMPLE_FREQ_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FREQ_MODE)
|
||||
|
||||
#define perf_arch_fetch_caller_regs(regs, __ip) do { \
|
||||
(regs)->psw.mask = 0; \
|
||||
(regs)->psw.addr = (__ip); \
|
||||
(regs)->gprs[15] = (unsigned long)__builtin_frame_address(0) - \
|
||||
offsetof(struct stack_frame, back_chain); \
|
||||
|
||||
@@ -272,18 +272,19 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
|
||||
goto no_pdev;
|
||||
|
||||
switch (ccdf->pec) {
|
||||
case 0x003a: /* Service Action or Error Recovery Successful */
|
||||
case 0x002a: /* Error event concerns FMB */
|
||||
case 0x002b:
|
||||
case 0x002c:
|
||||
break;
|
||||
case 0x0040: /* Service Action or Error Recovery Failed */
|
||||
case 0x003b:
|
||||
zpci_event_io_failure(pdev, pci_channel_io_perm_failure);
|
||||
break;
|
||||
default: /* PCI function left in the error state attempt to recover */
|
||||
ers_res = zpci_event_attempt_error_recovery(pdev);
|
||||
if (ers_res != PCI_ERS_RESULT_RECOVERED)
|
||||
zpci_event_io_failure(pdev, pci_channel_io_perm_failure);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Mark as frozen not permanently failed because the device
|
||||
* could be subsequently recovered by the platform.
|
||||
*/
|
||||
zpci_event_io_failure(pdev, pci_channel_io_frozen);
|
||||
break;
|
||||
}
|
||||
pci_dev_put(pdev);
|
||||
no_pdev:
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
* hardware. The allocated bandwidth percentage is rounded to the next
|
||||
* control step available on the hardware.
|
||||
*/
|
||||
static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r)
|
||||
static bool bw_validate(char *buf, u32 *data, struct rdt_resource *r)
|
||||
{
|
||||
unsigned long bw;
|
||||
int ret;
|
||||
u32 bw;
|
||||
|
||||
/*
|
||||
* Only linear delay values is supported for current Intel SKUs.
|
||||
@@ -40,16 +40,21 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r)
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = kstrtoul(buf, 10, &bw);
|
||||
ret = kstrtou32(buf, 10, &bw);
|
||||
if (ret) {
|
||||
rdt_last_cmd_printf("Non-decimal digit in MB value %s\n", buf);
|
||||
rdt_last_cmd_printf("Invalid MB value %s\n", buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((bw < r->membw.min_bw || bw > r->default_ctrl) &&
|
||||
!is_mba_sc(r)) {
|
||||
rdt_last_cmd_printf("MB value %ld out of range [%d,%d]\n", bw,
|
||||
r->membw.min_bw, r->default_ctrl);
|
||||
/* Nothing else to do if software controller is enabled. */
|
||||
if (is_mba_sc(r)) {
|
||||
*data = bw;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bw < r->membw.min_bw || bw > r->default_ctrl) {
|
||||
rdt_last_cmd_printf("MB value %u out of range [%d,%d]\n",
|
||||
bw, r->membw.min_bw, r->default_ctrl);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -63,7 +68,7 @@ int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
|
||||
struct resctrl_staged_config *cfg;
|
||||
u32 closid = data->rdtgrp->closid;
|
||||
struct rdt_resource *r = s->res;
|
||||
unsigned long bw_val;
|
||||
u32 bw_val;
|
||||
|
||||
cfg = &d->staged_config[s->conf_type];
|
||||
if (cfg->have_new_ctrl) {
|
||||
|
||||
@@ -62,8 +62,12 @@ static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index)
|
||||
u64 pdpte;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Note, nCR3 is "assumed" to be 32-byte aligned, i.e. the CPU ignores
|
||||
* nCR3[4:0] when loading PDPTEs from memory.
|
||||
*/
|
||||
ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(cr3), &pdpte,
|
||||
offset_in_page(cr3) + index * 8, 8);
|
||||
(cr3 & GENMASK(11, 5)) + index * 8, 8);
|
||||
if (ret)
|
||||
return 0;
|
||||
return pdpte;
|
||||
|
||||
@@ -3117,10 +3117,12 @@ void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
||||
bfq_put_queue(bfqq);
|
||||
}
|
||||
|
||||
static void
|
||||
bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic,
|
||||
struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
|
||||
static struct bfq_queue *bfq_merge_bfqqs(struct bfq_data *bfqd,
|
||||
struct bfq_io_cq *bic,
|
||||
struct bfq_queue *bfqq)
|
||||
{
|
||||
struct bfq_queue *new_bfqq = bfqq->new_bfqq;
|
||||
|
||||
bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu",
|
||||
(unsigned long)new_bfqq->pid);
|
||||
/* Save weight raising and idle window of the merged queues */
|
||||
@@ -3214,6 +3216,8 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic,
|
||||
bfq_reassign_last_bfqq(bfqq, new_bfqq);
|
||||
|
||||
bfq_release_process_ref(bfqd, bfqq);
|
||||
|
||||
return new_bfqq;
|
||||
}
|
||||
|
||||
static bool bfq_allow_bio_merge(struct request_queue *q, struct request *rq,
|
||||
@@ -3249,14 +3253,8 @@ static bool bfq_allow_bio_merge(struct request_queue *q, struct request *rq,
|
||||
* fulfilled, i.e., bic can be redirected to new_bfqq
|
||||
* and bfqq can be put.
|
||||
*/
|
||||
bfq_merge_bfqqs(bfqd, bfqd->bio_bic, bfqq,
|
||||
new_bfqq);
|
||||
/*
|
||||
* If we get here, bio will be queued into new_queue,
|
||||
* so use new_bfqq to decide whether bio and rq can be
|
||||
* merged.
|
||||
*/
|
||||
bfqq = new_bfqq;
|
||||
while (bfqq != new_bfqq)
|
||||
bfqq = bfq_merge_bfqqs(bfqd, bfqd->bio_bic, bfqq);
|
||||
|
||||
/*
|
||||
* Change also bqfd->bio_bfqq, as
|
||||
@@ -5616,9 +5614,7 @@ bfq_do_early_stable_merge(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
* state before killing it.
|
||||
*/
|
||||
bfqq->bic = bic;
|
||||
bfq_merge_bfqqs(bfqd, bic, bfqq, new_bfqq);
|
||||
|
||||
return new_bfqq;
|
||||
return bfq_merge_bfqqs(bfqd, bic, bfqq);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6066,6 +6062,7 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
bool waiting, idle_timer_disabled = false;
|
||||
|
||||
if (new_bfqq) {
|
||||
struct bfq_queue *old_bfqq = bfqq;
|
||||
/*
|
||||
* Release the request's reference to the old bfqq
|
||||
* and make sure one is taken to the shared queue.
|
||||
@@ -6081,18 +6078,18 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
* then complete the merge and redirect it to
|
||||
* new_bfqq.
|
||||
*/
|
||||
if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq)
|
||||
bfq_merge_bfqqs(bfqd, RQ_BIC(rq),
|
||||
bfqq, new_bfqq);
|
||||
if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) {
|
||||
while (bfqq != new_bfqq)
|
||||
bfqq = bfq_merge_bfqqs(bfqd, RQ_BIC(rq), bfqq);
|
||||
}
|
||||
|
||||
bfq_clear_bfqq_just_created(bfqq);
|
||||
bfq_clear_bfqq_just_created(old_bfqq);
|
||||
/*
|
||||
* rq is about to be enqueued into new_bfqq,
|
||||
* release rq reference on bfqq
|
||||
*/
|
||||
bfq_put_queue(bfqq);
|
||||
bfq_put_queue(old_bfqq);
|
||||
rq->elv.priv[1] = new_bfqq;
|
||||
bfqq = new_bfqq;
|
||||
}
|
||||
|
||||
bfq_update_io_thinktime(bfqd, bfqq);
|
||||
|
||||
@@ -121,6 +121,17 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
|
||||
},
|
||||
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Samsung galaxybook2 ,initial _LID device notification returns
|
||||
* lid closed.
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "750XED"),
|
||||
},
|
||||
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/topology.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/units.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <acpi/cppc_acpi.h>
|
||||
|
||||
@@ -1664,3 +1667,116 @@ unsigned int cppc_get_transition_latency(int cpu_num)
|
||||
return latency_ns;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_get_transition_latency);
|
||||
|
||||
/* Minimum struct length needed for the DMI processor entry we want */
|
||||
#define DMI_ENTRY_PROCESSOR_MIN_LENGTH 48
|
||||
|
||||
/* Offset in the DMI processor structure for the max frequency */
|
||||
#define DMI_PROCESSOR_MAX_SPEED 0x14
|
||||
|
||||
/* Callback function used to retrieve the max frequency from DMI */
|
||||
static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
|
||||
{
|
||||
const u8 *dmi_data = (const u8 *)dm;
|
||||
u16 *mhz = (u16 *)private;
|
||||
|
||||
if (dm->type == DMI_ENTRY_PROCESSOR &&
|
||||
dm->length >= DMI_ENTRY_PROCESSOR_MIN_LENGTH) {
|
||||
u16 val = (u16)get_unaligned((const u16 *)
|
||||
(dmi_data + DMI_PROCESSOR_MAX_SPEED));
|
||||
*mhz = val > *mhz ? val : *mhz;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up the max frequency in DMI */
|
||||
static u64 cppc_get_dmi_max_khz(void)
|
||||
{
|
||||
u16 mhz = 0;
|
||||
|
||||
dmi_walk(cppc_find_dmi_mhz, &mhz);
|
||||
|
||||
/*
|
||||
* Real stupid fallback value, just in case there is no
|
||||
* actual value set.
|
||||
*/
|
||||
mhz = mhz ? mhz : 1;
|
||||
|
||||
return KHZ_PER_MHZ * mhz;
|
||||
}
|
||||
|
||||
/*
|
||||
* If CPPC lowest_freq and nominal_freq registers are exposed then we can
|
||||
* use them to convert perf to freq and vice versa. The conversion is
|
||||
* extrapolated as an affine function passing by the 2 points:
|
||||
* - (Low perf, Low freq)
|
||||
* - (Nominal perf, Nominal freq)
|
||||
*/
|
||||
unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf)
|
||||
{
|
||||
s64 retval, offset = 0;
|
||||
static u64 max_khz;
|
||||
u64 mul, div;
|
||||
|
||||
if (caps->lowest_freq && caps->nominal_freq) {
|
||||
/* Avoid special case when nominal_freq is equal to lowest_freq */
|
||||
if (caps->lowest_freq == caps->nominal_freq) {
|
||||
mul = caps->nominal_freq;
|
||||
div = caps->nominal_perf;
|
||||
} else {
|
||||
mul = caps->nominal_freq - caps->lowest_freq;
|
||||
div = caps->nominal_perf - caps->lowest_perf;
|
||||
}
|
||||
mul *= KHZ_PER_MHZ;
|
||||
offset = caps->nominal_freq * KHZ_PER_MHZ -
|
||||
div64_u64(caps->nominal_perf * mul, div);
|
||||
} else {
|
||||
if (!max_khz)
|
||||
max_khz = cppc_get_dmi_max_khz();
|
||||
mul = max_khz;
|
||||
div = caps->highest_perf;
|
||||
}
|
||||
|
||||
retval = offset + div64_u64(perf * mul, div);
|
||||
if (retval >= 0)
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_perf_to_khz);
|
||||
|
||||
unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq)
|
||||
{
|
||||
s64 retval, offset = 0;
|
||||
static u64 max_khz;
|
||||
u64 mul, div;
|
||||
|
||||
if (caps->lowest_freq && caps->nominal_freq) {
|
||||
/* Avoid special case when nominal_freq is equal to lowest_freq */
|
||||
if (caps->lowest_freq == caps->nominal_freq) {
|
||||
mul = caps->nominal_perf;
|
||||
div = caps->nominal_freq;
|
||||
} else {
|
||||
mul = caps->nominal_perf - caps->lowest_perf;
|
||||
div = caps->nominal_freq - caps->lowest_freq;
|
||||
}
|
||||
/*
|
||||
* We don't need to convert to kHz for computing offset and can
|
||||
* directly use nominal_freq and lowest_freq as the div64_u64
|
||||
* will remove the frequency unit.
|
||||
*/
|
||||
offset = caps->nominal_perf -
|
||||
div64_u64(caps->nominal_freq * mul, div);
|
||||
/* But we need it for computing the perf level. */
|
||||
div *= KHZ_PER_MHZ;
|
||||
} else {
|
||||
if (!max_khz)
|
||||
max_khz = cppc_get_dmi_max_khz();
|
||||
mul = caps->highest_perf;
|
||||
div = max_khz;
|
||||
}
|
||||
|
||||
retval = offset + div64_u64(freq * mul, div);
|
||||
if (retval >= 0)
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_khz_to_perf);
|
||||
|
||||
@@ -52,7 +52,7 @@ struct prm_context_buffer {
|
||||
static LIST_HEAD(prm_module_list);
|
||||
|
||||
struct prm_handler_info {
|
||||
guid_t guid;
|
||||
efi_guid_t guid;
|
||||
void *handler_addr;
|
||||
u64 static_data_buffer_addr;
|
||||
u64 acpi_param_buffer_addr;
|
||||
@@ -72,17 +72,21 @@ struct prm_module_info {
|
||||
struct prm_handler_info handlers[];
|
||||
};
|
||||
|
||||
static u64 efi_pa_va_lookup(u64 pa)
|
||||
static u64 efi_pa_va_lookup(efi_guid_t *guid, u64 pa)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
u64 pa_offset = pa & ~PAGE_MASK;
|
||||
u64 page = pa & PAGE_MASK;
|
||||
|
||||
for_each_efi_memory_desc(md) {
|
||||
if (md->phys_addr < pa && pa < md->phys_addr + PAGE_SIZE * md->num_pages)
|
||||
if ((md->attribute & EFI_MEMORY_RUNTIME) &&
|
||||
(md->phys_addr < pa && pa < md->phys_addr + PAGE_SIZE * md->num_pages)) {
|
||||
return pa_offset + md->virt_addr + page - md->phys_addr;
|
||||
}
|
||||
}
|
||||
|
||||
pr_warn("Failed to find VA for GUID: %pUL, PA: 0x%llx", guid, pa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -148,9 +152,15 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end)
|
||||
th = &tm->handlers[cur_handler];
|
||||
|
||||
guid_copy(&th->guid, (guid_t *)handler_info->handler_guid);
|
||||
th->handler_addr = (void *)efi_pa_va_lookup(handler_info->handler_address);
|
||||
th->static_data_buffer_addr = efi_pa_va_lookup(handler_info->static_data_buffer_address);
|
||||
th->acpi_param_buffer_addr = efi_pa_va_lookup(handler_info->acpi_param_buffer_address);
|
||||
th->handler_addr =
|
||||
(void *)efi_pa_va_lookup(&th->guid, handler_info->handler_address);
|
||||
|
||||
th->static_data_buffer_addr =
|
||||
efi_pa_va_lookup(&th->guid, handler_info->static_data_buffer_address);
|
||||
|
||||
th->acpi_param_buffer_addr =
|
||||
efi_pa_va_lookup(&th->guid, handler_info->acpi_param_buffer_address);
|
||||
|
||||
} while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info)));
|
||||
|
||||
return 0;
|
||||
@@ -253,6 +263,13 @@ static acpi_status acpi_platformrt_space_handler(u32 function,
|
||||
if (!handler || !module)
|
||||
goto invalid_guid;
|
||||
|
||||
if (!handler->handler_addr ||
|
||||
!handler->static_data_buffer_addr ||
|
||||
!handler->acpi_param_buffer_addr) {
|
||||
buffer->prm_status = PRM_HANDLER_ERROR;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
ACPI_COPY_NAMESEG(context.signature, "PRMC");
|
||||
context.revision = 0x0;
|
||||
context.reserved = 0x0;
|
||||
|
||||
@@ -502,6 +502,13 @@ static const struct dmi_system_id tongfang_gm_rg[] = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* LG Electronics 16T90SP */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "16T90SP"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/irq_work.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/time.h>
|
||||
@@ -27,12 +26,6 @@
|
||||
|
||||
#include <acpi/cppc_acpi.h>
|
||||
|
||||
/* Minimum struct length needed for the DMI processor entry we want */
|
||||
#define DMI_ENTRY_PROCESSOR_MIN_LENGTH 48
|
||||
|
||||
/* Offset in the DMI processor structure for the max frequency */
|
||||
#define DMI_PROCESSOR_MAX_SPEED 0x14
|
||||
|
||||
/*
|
||||
* This list contains information parsed from per CPU ACPI _CPC and _PSD
|
||||
* structures: e.g. the highest and lowest supported performance, capabilities,
|
||||
@@ -288,97 +281,9 @@ static inline void cppc_freq_invariance_exit(void)
|
||||
}
|
||||
#endif /* CONFIG_ACPI_CPPC_CPUFREQ_FIE */
|
||||
|
||||
/* Callback function used to retrieve the max frequency from DMI */
|
||||
static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
|
||||
{
|
||||
const u8 *dmi_data = (const u8 *)dm;
|
||||
u16 *mhz = (u16 *)private;
|
||||
|
||||
if (dm->type == DMI_ENTRY_PROCESSOR &&
|
||||
dm->length >= DMI_ENTRY_PROCESSOR_MIN_LENGTH) {
|
||||
u16 val = (u16)get_unaligned((const u16 *)
|
||||
(dmi_data + DMI_PROCESSOR_MAX_SPEED));
|
||||
*mhz = val > *mhz ? val : *mhz;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up the max frequency in DMI */
|
||||
static u64 cppc_get_dmi_max_khz(void)
|
||||
{
|
||||
u16 mhz = 0;
|
||||
|
||||
dmi_walk(cppc_find_dmi_mhz, &mhz);
|
||||
|
||||
/*
|
||||
* Real stupid fallback value, just in case there is no
|
||||
* actual value set.
|
||||
*/
|
||||
mhz = mhz ? mhz : 1;
|
||||
|
||||
return (1000 * mhz);
|
||||
}
|
||||
|
||||
/*
|
||||
* If CPPC lowest_freq and nominal_freq registers are exposed then we can
|
||||
* use them to convert perf to freq and vice versa. The conversion is
|
||||
* extrapolated as an affine function passing by the 2 points:
|
||||
* - (Low perf, Low freq)
|
||||
* - (Nominal perf, Nominal perf)
|
||||
*/
|
||||
static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu_data,
|
||||
unsigned int perf)
|
||||
{
|
||||
struct cppc_perf_caps *caps = &cpu_data->perf_caps;
|
||||
s64 retval, offset = 0;
|
||||
static u64 max_khz;
|
||||
u64 mul, div;
|
||||
|
||||
if (caps->lowest_freq && caps->nominal_freq) {
|
||||
mul = caps->nominal_freq - caps->lowest_freq;
|
||||
div = caps->nominal_perf - caps->lowest_perf;
|
||||
offset = caps->nominal_freq - div64_u64(caps->nominal_perf * mul, div);
|
||||
} else {
|
||||
if (!max_khz)
|
||||
max_khz = cppc_get_dmi_max_khz();
|
||||
mul = max_khz;
|
||||
div = caps->highest_perf;
|
||||
}
|
||||
|
||||
retval = offset + div64_u64(perf * mul, div);
|
||||
if (retval >= 0)
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu_data,
|
||||
unsigned int freq)
|
||||
{
|
||||
struct cppc_perf_caps *caps = &cpu_data->perf_caps;
|
||||
s64 retval, offset = 0;
|
||||
static u64 max_khz;
|
||||
u64 mul, div;
|
||||
|
||||
if (caps->lowest_freq && caps->nominal_freq) {
|
||||
mul = caps->nominal_perf - caps->lowest_perf;
|
||||
div = caps->nominal_freq - caps->lowest_freq;
|
||||
offset = caps->nominal_perf - div64_u64(caps->nominal_freq * mul, div);
|
||||
} else {
|
||||
if (!max_khz)
|
||||
max_khz = cppc_get_dmi_max_khz();
|
||||
mul = caps->highest_perf;
|
||||
div = max_khz;
|
||||
}
|
||||
|
||||
retval = offset + div64_u64(freq * mul, div);
|
||||
if (retval >= 0)
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
|
||||
{
|
||||
struct cppc_cpudata *cpu_data = policy->driver_data;
|
||||
unsigned int cpu = policy->cpu;
|
||||
@@ -386,7 +291,7 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
|
||||
u32 desired_perf;
|
||||
int ret = 0;
|
||||
|
||||
desired_perf = cppc_cpufreq_khz_to_perf(cpu_data, target_freq);
|
||||
desired_perf = cppc_khz_to_perf(&cpu_data->perf_caps, target_freq);
|
||||
/* Return if it is exactly the same perf */
|
||||
if (desired_perf == cpu_data->perf_ctrls.desired_perf)
|
||||
return ret;
|
||||
@@ -414,7 +319,7 @@ static unsigned int cppc_cpufreq_fast_switch(struct cpufreq_policy *policy,
|
||||
u32 desired_perf;
|
||||
int ret;
|
||||
|
||||
desired_perf = cppc_cpufreq_khz_to_perf(cpu_data, target_freq);
|
||||
desired_perf = cppc_khz_to_perf(&cpu_data->perf_caps, target_freq);
|
||||
cpu_data->perf_ctrls.desired_perf = desired_perf;
|
||||
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
|
||||
|
||||
@@ -527,7 +432,7 @@ static int cppc_get_cpu_power(struct device *cpu_dev,
|
||||
min_step = min_cap / CPPC_EM_CAP_STEP;
|
||||
max_step = max_cap / CPPC_EM_CAP_STEP;
|
||||
|
||||
perf_prev = cppc_cpufreq_khz_to_perf(cpu_data, *KHz);
|
||||
perf_prev = cppc_khz_to_perf(perf_caps, *KHz);
|
||||
step = perf_prev / perf_step;
|
||||
|
||||
if (step > max_step)
|
||||
@@ -547,8 +452,8 @@ static int cppc_get_cpu_power(struct device *cpu_dev,
|
||||
perf = step * perf_step;
|
||||
}
|
||||
|
||||
*KHz = cppc_cpufreq_perf_to_khz(cpu_data, perf);
|
||||
perf_check = cppc_cpufreq_khz_to_perf(cpu_data, *KHz);
|
||||
*KHz = cppc_perf_to_khz(perf_caps, perf);
|
||||
perf_check = cppc_khz_to_perf(perf_caps, *KHz);
|
||||
step_check = perf_check / perf_step;
|
||||
|
||||
/*
|
||||
@@ -558,8 +463,8 @@ static int cppc_get_cpu_power(struct device *cpu_dev,
|
||||
*/
|
||||
while ((*KHz == prev_freq) || (step_check != step)) {
|
||||
perf++;
|
||||
*KHz = cppc_cpufreq_perf_to_khz(cpu_data, perf);
|
||||
perf_check = cppc_cpufreq_khz_to_perf(cpu_data, *KHz);
|
||||
*KHz = cppc_perf_to_khz(perf_caps, perf);
|
||||
perf_check = cppc_khz_to_perf(perf_caps, *KHz);
|
||||
step_check = perf_check / perf_step;
|
||||
}
|
||||
|
||||
@@ -588,7 +493,7 @@ static int cppc_get_cpu_cost(struct device *cpu_dev, unsigned long KHz,
|
||||
perf_caps = &cpu_data->perf_caps;
|
||||
max_cap = arch_scale_cpu_capacity(cpu_dev->id);
|
||||
|
||||
perf_prev = cppc_cpufreq_khz_to_perf(cpu_data, KHz);
|
||||
perf_prev = cppc_khz_to_perf(perf_caps, KHz);
|
||||
perf_step = CPPC_EM_CAP_STEP * perf_caps->highest_perf / max_cap;
|
||||
step = perf_prev / perf_step;
|
||||
|
||||
@@ -676,10 +581,6 @@ static struct cppc_cpudata *cppc_cpufreq_get_cpu_data(unsigned int cpu)
|
||||
goto free_mask;
|
||||
}
|
||||
|
||||
/* Convert the lowest and nominal freq from MHz to KHz */
|
||||
cpu_data->perf_caps.lowest_freq *= 1000;
|
||||
cpu_data->perf_caps.nominal_freq *= 1000;
|
||||
|
||||
list_add(&cpu_data->node, &cpu_data_list);
|
||||
|
||||
return cpu_data;
|
||||
@@ -721,20 +622,16 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
* Set min to lowest nonlinear perf to avoid any efficiency penalty (see
|
||||
* Section 8.4.7.1.1.5 of ACPI 6.1 spec)
|
||||
*/
|
||||
policy->min = cppc_cpufreq_perf_to_khz(cpu_data,
|
||||
caps->lowest_nonlinear_perf);
|
||||
policy->max = cppc_cpufreq_perf_to_khz(cpu_data,
|
||||
caps->nominal_perf);
|
||||
policy->min = cppc_perf_to_khz(caps, caps->lowest_nonlinear_perf);
|
||||
policy->max = cppc_perf_to_khz(caps, caps->nominal_perf);
|
||||
|
||||
/*
|
||||
* Set cpuinfo.min_freq to Lowest to make the full range of performance
|
||||
* available if userspace wants to use any perf between lowest & lowest
|
||||
* nonlinear perf
|
||||
*/
|
||||
policy->cpuinfo.min_freq = cppc_cpufreq_perf_to_khz(cpu_data,
|
||||
caps->lowest_perf);
|
||||
policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu_data,
|
||||
caps->nominal_perf);
|
||||
policy->cpuinfo.min_freq = cppc_perf_to_khz(caps, caps->lowest_perf);
|
||||
policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->nominal_perf);
|
||||
|
||||
policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu);
|
||||
policy->shared_type = cpu_data->shared_type;
|
||||
@@ -770,7 +667,7 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
boost_supported = true;
|
||||
|
||||
/* Set policy->cur to max now. The governors will adjust later. */
|
||||
policy->cur = cppc_cpufreq_perf_to_khz(cpu_data, caps->highest_perf);
|
||||
policy->cur = cppc_perf_to_khz(caps, caps->highest_perf);
|
||||
cpu_data->perf_ctrls.desired_perf = caps->highest_perf;
|
||||
|
||||
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
|
||||
@@ -865,7 +762,7 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
|
||||
delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0,
|
||||
&fb_ctrs_t1);
|
||||
|
||||
return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf);
|
||||
return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf);
|
||||
}
|
||||
|
||||
static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
|
||||
@@ -880,11 +777,9 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
|
||||
}
|
||||
|
||||
if (state)
|
||||
policy->max = cppc_cpufreq_perf_to_khz(cpu_data,
|
||||
caps->highest_perf);
|
||||
policy->max = cppc_perf_to_khz(caps, caps->highest_perf);
|
||||
else
|
||||
policy->max = cppc_cpufreq_perf_to_khz(cpu_data,
|
||||
caps->nominal_perf);
|
||||
policy->max = cppc_perf_to_khz(caps, caps->nominal_perf);
|
||||
policy->cpuinfo.max_freq = policy->max;
|
||||
|
||||
ret = freq_qos_update_request(policy->max_freq_req, policy->max);
|
||||
@@ -944,7 +839,7 @@ static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu)
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
|
||||
return cppc_cpufreq_perf_to_khz(cpu_data, desired_perf);
|
||||
return cppc_perf_to_khz(&cpu_data->perf_caps, desired_perf);
|
||||
}
|
||||
|
||||
static void cppc_check_hisi_workaround(void)
|
||||
|
||||
@@ -107,6 +107,7 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
|
||||
struct acpi_buffer *params)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_object *obj;
|
||||
union acpi_object atif_arg_elements[2];
|
||||
struct acpi_object_list atif_arg;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
@@ -129,16 +130,24 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
|
||||
|
||||
status = acpi_evaluate_object(atif->handle, NULL, &atif_arg,
|
||||
&buffer);
|
||||
obj = (union acpi_object *)buffer.pointer;
|
||||
|
||||
/* Fail only if calling the method fails and ATIF is supported */
|
||||
/* Fail if calling the method fails and ATIF is supported */
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
|
||||
DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
|
||||
acpi_format_exception(status));
|
||||
kfree(buffer.pointer);
|
||||
kfree(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buffer.pointer;
|
||||
if (obj->type != ACPI_TYPE_BUFFER) {
|
||||
DRM_DEBUG_DRIVER("bad object returned from ATIF: %d\n",
|
||||
obj->type);
|
||||
kfree(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1038,8 +1038,10 @@ int amdgpu_mes_add_ring(struct amdgpu_device *adev, int gang_id,
|
||||
|
||||
r = amdgpu_ring_init(adev, ring, 1024, NULL, 0,
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
if (r) {
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
goto clean_up_memory;
|
||||
}
|
||||
|
||||
amdgpu_mes_ring_to_queue_props(adev, ring, &qprops);
|
||||
|
||||
@@ -1072,7 +1074,6 @@ clean_up_ring:
|
||||
amdgpu_ring_fini(ring);
|
||||
clean_up_memory:
|
||||
kfree(ring);
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -818,6 +818,8 @@ bool is_psr_su_specific_panel(struct dc_link *link)
|
||||
isPSRSUSupported = false;
|
||||
else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x03)
|
||||
isPSRSUSupported = false;
|
||||
else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x01)
|
||||
isPSRSUSupported = false;
|
||||
else if (dpcd_caps->psr_info.force_psrsu_cap == 0x1)
|
||||
isPSRSUSupported = true;
|
||||
}
|
||||
|
||||
@@ -1106,21 +1106,20 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
|
||||
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
|
||||
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
|
||||
|
||||
if (!dpu_enc->hw_pp[i]) {
|
||||
phys->hw_pp = dpu_enc->hw_pp[i];
|
||||
if (!phys->hw_pp) {
|
||||
DPU_ERROR_ENC(dpu_enc,
|
||||
"no pp block assigned at idx: %d\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hw_ctl[i]) {
|
||||
phys->hw_ctl = i < num_ctl ? to_dpu_hw_ctl(hw_ctl[i]) : NULL;
|
||||
if (!phys->hw_ctl) {
|
||||
DPU_ERROR_ENC(dpu_enc,
|
||||
"no ctl block assigned at idx: %d\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
phys->hw_pp = dpu_enc->hw_pp[i];
|
||||
phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
|
||||
|
||||
phys->cached_mode = crtc_state->adjusted_mode;
|
||||
if (phys->ops.atomic_mode_set)
|
||||
phys->ops.atomic_mode_set(phys, crtc_state, conn_state);
|
||||
|
||||
@@ -61,6 +61,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
|
||||
intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
|
||||
intf_cfg.stream_sel = cmd_enc->stream_sel;
|
||||
intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
|
||||
intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc);
|
||||
ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
|
||||
|
||||
/* setup which pp blk will connect to this intf */
|
||||
|
||||
@@ -276,7 +276,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
|
||||
intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID;
|
||||
intf_cfg.stream_sel = 0; /* Don't care value for video mode */
|
||||
intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
|
||||
if (phys_enc->hw_pp->merge_3d)
|
||||
intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc);
|
||||
if (intf_cfg.mode_3d && phys_enc->hw_pp->merge_3d)
|
||||
intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx;
|
||||
|
||||
spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
|
||||
|
||||
@@ -26,7 +26,7 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
|
||||
end_addr = base_addr + aligned_len;
|
||||
|
||||
if (!(*reg))
|
||||
*reg = kzalloc(len_padded, GFP_KERNEL);
|
||||
*reg = kvzalloc(len_padded, GFP_KERNEL);
|
||||
|
||||
if (*reg)
|
||||
dump_addr = *reg;
|
||||
@@ -48,20 +48,21 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
|
||||
}
|
||||
}
|
||||
|
||||
static void msm_disp_state_print_regs(u32 **reg, u32 len, void __iomem *base_addr,
|
||||
struct drm_printer *p)
|
||||
static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len,
|
||||
void __iomem *base_addr, struct drm_printer *p)
|
||||
{
|
||||
int i;
|
||||
u32 *dump_addr = NULL;
|
||||
void __iomem *addr;
|
||||
u32 num_rows;
|
||||
|
||||
if (!dump_addr) {
|
||||
drm_printf(p, "Registers not stored\n");
|
||||
return;
|
||||
}
|
||||
|
||||
addr = base_addr;
|
||||
num_rows = len / REG_DUMP_ALIGN;
|
||||
|
||||
if (*reg)
|
||||
dump_addr = *reg;
|
||||
|
||||
for (i = 0; i < num_rows; i++) {
|
||||
drm_printf(p, "0x%lx : %08x %08x %08x %08x\n",
|
||||
(unsigned long)(addr - base_addr),
|
||||
@@ -89,7 +90,7 @@ void msm_disp_state_print(struct msm_disp_state *state, struct drm_printer *p)
|
||||
|
||||
list_for_each_entry_safe(block, tmp, &state->blocks, node) {
|
||||
drm_printf(p, "====================%s================\n", block->name);
|
||||
msm_disp_state_print_regs(&block->state, block->size, block->base_addr, p);
|
||||
msm_disp_state_print_regs(block->state, block->size, block->base_addr, p);
|
||||
}
|
||||
|
||||
drm_printf(p, "===================dpu drm state================\n");
|
||||
@@ -161,7 +162,7 @@ void msm_disp_state_free(void *data)
|
||||
|
||||
list_for_each_entry_safe(block, tmp, &disp_state->blocks, node) {
|
||||
list_del(&block->node);
|
||||
kfree(block->state);
|
||||
kvfree(block->state);
|
||||
kfree(block);
|
||||
}
|
||||
|
||||
|
||||
@@ -576,7 +576,7 @@ static unsigned long dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_bo
|
||||
struct drm_display_mode *mode = msm_host->mode;
|
||||
unsigned long pclk_rate;
|
||||
|
||||
pclk_rate = mode->clock * 1000;
|
||||
pclk_rate = mode->clock * 1000u;
|
||||
|
||||
/*
|
||||
* For bonded DSI mode, the current DRM mode has the complete width of the
|
||||
|
||||
@@ -139,7 +139,15 @@ int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags,
|
||||
flags |= VBOX_MOUSE_POINTER_VISIBLE;
|
||||
}
|
||||
|
||||
p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA,
|
||||
/*
|
||||
* The 4 extra bytes come from switching struct vbva_mouse_pointer_shape
|
||||
* from having a 4 bytes fixed array at the end to using a proper VLA
|
||||
* at the end. These 4 extra bytes were not subtracted from sizeof(*p)
|
||||
* before the switch to the VLA, so this way the behavior is unchanged.
|
||||
* Chances are these 4 extra bytes are not necessary but they are kept
|
||||
* to avoid regressions.
|
||||
*/
|
||||
p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len + 4, HGSMI_CH_VBVA,
|
||||
VBVA_MOUSE_POINTER_SHAPE);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -351,10 +351,8 @@ struct vbva_mouse_pointer_shape {
|
||||
* Bytes in the gap between the AND and the XOR mask are undefined.
|
||||
* XOR mask scanlines have no gap between them and size of XOR mask is:
|
||||
* xor_len = width * 4 * height.
|
||||
*
|
||||
* Preallocate 4 bytes for accessing actual data as p->data.
|
||||
*/
|
||||
u8 data[4];
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/* pointer is visible */
|
||||
|
||||
@@ -1028,6 +1028,10 @@ static int vmw_stdu_connector_atomic_check(struct drm_connector *conn,
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
|
||||
conn_state = drm_atomic_get_connector_state(state, conn);
|
||||
|
||||
if (IS_ERR(conn_state))
|
||||
return PTR_ERR(conn_state);
|
||||
|
||||
du = vmw_connector_to_stdu(conn);
|
||||
|
||||
if (!conn_state->crtc)
|
||||
|
||||
@@ -1245,7 +1245,8 @@ static int bma400_activity_event_en(struct bma400_data *data,
|
||||
static int bma400_tap_event_en(struct bma400_data *data,
|
||||
enum iio_event_direction dir, int state)
|
||||
{
|
||||
unsigned int mask, field_value;
|
||||
unsigned int mask;
|
||||
unsigned int field_value = 0;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
||||
@@ -71,25 +71,26 @@ config ADMV1014
|
||||
module will be called admv1014.
|
||||
|
||||
config ADMV4420
|
||||
tristate "Analog Devices ADMV4420 K Band Downconverter"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices K Band
|
||||
Downconverter with integrated Fractional-N PLL and VCO.
|
||||
tristate "Analog Devices ADMV4420 K Band Downconverter"
|
||||
depends on SPI
|
||||
select REGMAP_SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices K Band
|
||||
Downconverter with integrated Fractional-N PLL and VCO.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called admv4420.
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called admv4420.
|
||||
|
||||
config ADRF6780
|
||||
tristate "Analog Devices ADRF6780 Microwave Upconverter"
|
||||
depends on SPI
|
||||
depends on COMMON_CLK
|
||||
help
|
||||
Say yes here to build support for Analog Devices ADRF6780
|
||||
5.9 GHz to 23.6 GHz, Wideband, Microwave Upconverter.
|
||||
tristate "Analog Devices ADRF6780 Microwave Upconverter"
|
||||
depends on SPI
|
||||
depends on COMMON_CLK
|
||||
help
|
||||
Say yes here to build support for Analog Devices ADRF6780
|
||||
5.9 GHz to 23.6 GHz, Wideband, Microwave Upconverter.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called adrf6780.
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called adrf6780.
|
||||
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
@@ -169,7 +169,7 @@ struct bnxt_qplib_swqe {
|
||||
};
|
||||
u32 q_key;
|
||||
u32 dst_qp;
|
||||
u16 avid;
|
||||
u32 avid;
|
||||
} send;
|
||||
|
||||
/* Send Raw Ethernet and QP1 */
|
||||
|
||||
@@ -249,7 +249,7 @@ int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
|
||||
/* failed with status */
|
||||
dev_err(&rcfw->pdev->dev, "cmdq[%#x]=%#x status %#x\n",
|
||||
cookie, opcode, evnt->status);
|
||||
rc = -EFAULT;
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -244,6 +244,8 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
|
||||
sginfo.pgsize = npde * pg_size;
|
||||
sginfo.npages = 1;
|
||||
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
/* Alloc PBL pages */
|
||||
sginfo.npages = npbl;
|
||||
@@ -255,22 +257,9 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
|
||||
dst_virt_ptr =
|
||||
(dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr;
|
||||
src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr;
|
||||
if (hwq_attr->type == HWQ_TYPE_MR) {
|
||||
/* For MR it is expected that we supply only 1 contigous
|
||||
* page i.e only 1 entry in the PDL that will contain
|
||||
* all the PBLs for the user supplied memory region
|
||||
*/
|
||||
for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count;
|
||||
i++)
|
||||
dst_virt_ptr[0][i] = src_phys_ptr[i] |
|
||||
flag;
|
||||
} else {
|
||||
for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count;
|
||||
i++)
|
||||
dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] =
|
||||
src_phys_ptr[i] |
|
||||
PTU_PDE_VALID;
|
||||
}
|
||||
for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++)
|
||||
dst_virt_ptr[0][i] = src_phys_ptr[i] | flag;
|
||||
|
||||
/* Alloc or init PTEs */
|
||||
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_2],
|
||||
hwq_attr->sginfo);
|
||||
|
||||
@@ -2086,7 +2086,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
|
||||
err = -ENOMEM;
|
||||
if (n->dev->flags & IFF_LOOPBACK) {
|
||||
if (iptype == 4)
|
||||
pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip);
|
||||
pdev = __ip_dev_find(&init_net, *(__be32 *)peer_ip, false);
|
||||
else if (IS_ENABLED(CONFIG_IPV6))
|
||||
for_each_netdev(&init_net, pdev) {
|
||||
if (ipv6_chk_addr(&init_net,
|
||||
@@ -2101,12 +2101,12 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (is_vlan_dev(pdev))
|
||||
pdev = vlan_dev_real_dev(pdev);
|
||||
ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t,
|
||||
n, pdev, rt_tos2priority(tos));
|
||||
if (!ep->l2t) {
|
||||
dev_put(pdev);
|
||||
if (!ep->l2t)
|
||||
goto out;
|
||||
}
|
||||
ep->mtu = pdev->mtu;
|
||||
ep->tx_chan = cxgb4_port_chan(pdev);
|
||||
ep->smac_idx = ((struct port_info *)netdev_priv(pdev))->smt_idx;
|
||||
@@ -2119,7 +2119,6 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
|
||||
ep->rss_qid = cdev->rdev.lldi.rxq_ids[
|
||||
cxgb4_port_idx(pdev) * step];
|
||||
set_tcp_window(ep, (struct port_info *)netdev_priv(pdev));
|
||||
dev_put(pdev);
|
||||
} else {
|
||||
pdev = get_real_dev(n->dev);
|
||||
ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t,
|
||||
|
||||
@@ -3584,7 +3584,7 @@ void irdma_free_lsmm_rsrc(struct irdma_qp *iwqp)
|
||||
/**
|
||||
* irdma_accept - registered call for connection to be accepted
|
||||
* @cm_id: cm information for passive connection
|
||||
* @conn_param: accpet parameters
|
||||
* @conn_param: accept parameters
|
||||
*/
|
||||
int irdma_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
||||
{
|
||||
|
||||
@@ -68,6 +68,8 @@ MODULE_LICENSE("Dual BSD/GPL");
|
||||
static u64 srpt_service_guid;
|
||||
static DEFINE_SPINLOCK(srpt_dev_lock); /* Protects srpt_dev_list. */
|
||||
static LIST_HEAD(srpt_dev_list); /* List of srpt_device structures. */
|
||||
static DEFINE_MUTEX(srpt_mc_mutex); /* Protects srpt_memory_caches. */
|
||||
static DEFINE_XARRAY(srpt_memory_caches); /* See also srpt_memory_cache_entry */
|
||||
|
||||
static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;
|
||||
module_param(srp_max_req_size, int, 0444);
|
||||
@@ -105,6 +107,63 @@ static void srpt_recv_done(struct ib_cq *cq, struct ib_wc *wc);
|
||||
static void srpt_send_done(struct ib_cq *cq, struct ib_wc *wc);
|
||||
static void srpt_process_wait_list(struct srpt_rdma_ch *ch);
|
||||
|
||||
/* Type of the entries in srpt_memory_caches. */
|
||||
struct srpt_memory_cache_entry {
|
||||
refcount_t ref;
|
||||
struct kmem_cache *c;
|
||||
};
|
||||
|
||||
static struct kmem_cache *srpt_cache_get(unsigned int object_size)
|
||||
{
|
||||
struct srpt_memory_cache_entry *e;
|
||||
char name[32];
|
||||
void *res;
|
||||
|
||||
guard(mutex)(&srpt_mc_mutex);
|
||||
e = xa_load(&srpt_memory_caches, object_size);
|
||||
if (e) {
|
||||
refcount_inc(&e->ref);
|
||||
return e->c;
|
||||
}
|
||||
snprintf(name, sizeof(name), "srpt-%u", object_size);
|
||||
e = kmalloc(sizeof(*e), GFP_KERNEL);
|
||||
if (!e)
|
||||
return NULL;
|
||||
refcount_set(&e->ref, 1);
|
||||
e->c = kmem_cache_create(name, object_size, /*align=*/512, 0, NULL);
|
||||
if (!e->c)
|
||||
goto free_entry;
|
||||
res = xa_store(&srpt_memory_caches, object_size, e, GFP_KERNEL);
|
||||
if (xa_is_err(res))
|
||||
goto destroy_cache;
|
||||
return e->c;
|
||||
|
||||
destroy_cache:
|
||||
kmem_cache_destroy(e->c);
|
||||
|
||||
free_entry:
|
||||
kfree(e);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void srpt_cache_put(struct kmem_cache *c)
|
||||
{
|
||||
struct srpt_memory_cache_entry *e = NULL;
|
||||
unsigned long object_size;
|
||||
|
||||
guard(mutex)(&srpt_mc_mutex);
|
||||
xa_for_each(&srpt_memory_caches, object_size, e)
|
||||
if (e->c == c)
|
||||
break;
|
||||
if (WARN_ON_ONCE(!e))
|
||||
return;
|
||||
if (!refcount_dec_and_test(&e->ref))
|
||||
return;
|
||||
WARN_ON_ONCE(xa_erase(&srpt_memory_caches, object_size) != e);
|
||||
kmem_cache_destroy(e->c);
|
||||
kfree(e);
|
||||
}
|
||||
|
||||
/*
|
||||
* The only allowed channel state changes are those that change the channel
|
||||
* state into a state with a higher numerical value. Hence the new > prev test.
|
||||
@@ -2119,13 +2178,13 @@ static void srpt_release_channel_work(struct work_struct *w)
|
||||
ch->sport->sdev, ch->rq_size,
|
||||
ch->rsp_buf_cache, DMA_TO_DEVICE);
|
||||
|
||||
kmem_cache_destroy(ch->rsp_buf_cache);
|
||||
srpt_cache_put(ch->rsp_buf_cache);
|
||||
|
||||
srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_recv_ring,
|
||||
sdev, ch->rq_size,
|
||||
ch->req_buf_cache, DMA_FROM_DEVICE);
|
||||
|
||||
kmem_cache_destroy(ch->req_buf_cache);
|
||||
srpt_cache_put(ch->req_buf_cache);
|
||||
|
||||
kref_put(&ch->kref, srpt_free_ch);
|
||||
}
|
||||
@@ -2245,8 +2304,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
|
||||
INIT_LIST_HEAD(&ch->cmd_wait_list);
|
||||
ch->max_rsp_size = ch->sport->port_attrib.srp_max_rsp_size;
|
||||
|
||||
ch->rsp_buf_cache = kmem_cache_create("srpt-rsp-buf", ch->max_rsp_size,
|
||||
512, 0, NULL);
|
||||
ch->rsp_buf_cache = srpt_cache_get(ch->max_rsp_size);
|
||||
if (!ch->rsp_buf_cache)
|
||||
goto free_ch;
|
||||
|
||||
@@ -2280,8 +2338,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
|
||||
alignment_offset = round_up(imm_data_offset, 512) -
|
||||
imm_data_offset;
|
||||
req_sz = alignment_offset + imm_data_offset + srp_max_req_size;
|
||||
ch->req_buf_cache = kmem_cache_create("srpt-req-buf", req_sz,
|
||||
512, 0, NULL);
|
||||
ch->req_buf_cache = srpt_cache_get(req_sz);
|
||||
if (!ch->req_buf_cache)
|
||||
goto free_rsp_ring;
|
||||
|
||||
@@ -2478,7 +2535,7 @@ free_recv_ring:
|
||||
ch->req_buf_cache, DMA_FROM_DEVICE);
|
||||
|
||||
free_recv_cache:
|
||||
kmem_cache_destroy(ch->req_buf_cache);
|
||||
srpt_cache_put(ch->req_buf_cache);
|
||||
|
||||
free_rsp_ring:
|
||||
srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
|
||||
@@ -2486,7 +2543,7 @@ free_rsp_ring:
|
||||
ch->rsp_buf_cache, DMA_TO_DEVICE);
|
||||
|
||||
free_rsp_cache:
|
||||
kmem_cache_destroy(ch->rsp_buf_cache);
|
||||
srpt_cache_put(ch->rsp_buf_cache);
|
||||
|
||||
free_ch:
|
||||
if (rdma_cm_id)
|
||||
@@ -3055,7 +3112,7 @@ static void srpt_free_srq(struct srpt_device *sdev)
|
||||
srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
|
||||
sdev->srq_size, sdev->req_buf_cache,
|
||||
DMA_FROM_DEVICE);
|
||||
kmem_cache_destroy(sdev->req_buf_cache);
|
||||
srpt_cache_put(sdev->req_buf_cache);
|
||||
sdev->srq = NULL;
|
||||
}
|
||||
|
||||
@@ -3082,8 +3139,7 @@ static int srpt_alloc_srq(struct srpt_device *sdev)
|
||||
pr_debug("create SRQ #wr= %d max_allow=%d dev= %s\n", sdev->srq_size,
|
||||
sdev->device->attrs.max_srq_wr, dev_name(&device->dev));
|
||||
|
||||
sdev->req_buf_cache = kmem_cache_create("srpt-srq-req-buf",
|
||||
srp_max_req_size, 0, 0, NULL);
|
||||
sdev->req_buf_cache = srpt_cache_get(srp_max_req_size);
|
||||
if (!sdev->req_buf_cache)
|
||||
goto free_srq;
|
||||
|
||||
@@ -3105,7 +3161,7 @@ static int srpt_alloc_srq(struct srpt_device *sdev)
|
||||
return 0;
|
||||
|
||||
free_cache:
|
||||
kmem_cache_destroy(sdev->req_buf_cache);
|
||||
srpt_cache_put(sdev->req_buf_cache);
|
||||
|
||||
free_srq:
|
||||
ib_destroy_srq(srq);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
@@ -18,6 +19,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#define IRQC_IRQ_START 1
|
||||
#define IRQC_IRQ_COUNT 8
|
||||
@@ -55,12 +57,30 @@
|
||||
#define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
|
||||
#define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
|
||||
|
||||
struct rzg2l_irqc_priv {
|
||||
void __iomem *base;
|
||||
struct irq_fwspec fwspec[IRQC_NUM_IRQ];
|
||||
raw_spinlock_t lock;
|
||||
/**
|
||||
* struct rzg2l_irqc_reg_cache - registers cache (necessary for suspend/resume)
|
||||
* @iitsr: IITSR register
|
||||
* @titsr: TITSR registers
|
||||
*/
|
||||
struct rzg2l_irqc_reg_cache {
|
||||
u32 iitsr;
|
||||
u32 titsr[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rzg2l_irqc_priv - IRQ controller private data structure
|
||||
* @base: Controller's base address
|
||||
* @fwspec: IRQ firmware specific data
|
||||
* @lock: Lock to serialize access to hardware registers
|
||||
* @cache: Registers cache for suspend/resume
|
||||
*/
|
||||
static struct rzg2l_irqc_priv {
|
||||
void __iomem *base;
|
||||
struct irq_fwspec fwspec[IRQC_NUM_IRQ];
|
||||
raw_spinlock_t lock;
|
||||
struct rzg2l_irqc_reg_cache cache;
|
||||
} *rzg2l_irqc_data;
|
||||
|
||||
static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
|
||||
{
|
||||
return data->domain->host_data;
|
||||
@@ -276,6 +296,38 @@ static int rzg2l_irqc_set_type(struct irq_data *d, unsigned int type)
|
||||
return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
|
||||
}
|
||||
|
||||
static int rzg2l_irqc_irq_suspend(void)
|
||||
{
|
||||
struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache;
|
||||
void __iomem *base = rzg2l_irqc_data->base;
|
||||
|
||||
cache->iitsr = readl_relaxed(base + IITSR);
|
||||
for (u8 i = 0; i < 2; i++)
|
||||
cache->titsr[i] = readl_relaxed(base + TITSR(i));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rzg2l_irqc_irq_resume(void)
|
||||
{
|
||||
struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache;
|
||||
void __iomem *base = rzg2l_irqc_data->base;
|
||||
|
||||
/*
|
||||
* Restore only interrupt type. TSSRx will be restored at the
|
||||
* request of pin controller to avoid spurious interrupts due
|
||||
* to invalid PIN states.
|
||||
*/
|
||||
for (u8 i = 0; i < 2; i++)
|
||||
writel_relaxed(cache->titsr[i], base + TITSR(i));
|
||||
writel_relaxed(cache->iitsr, base + IITSR);
|
||||
}
|
||||
|
||||
static struct syscore_ops rzg2l_irqc_syscore_ops = {
|
||||
.suspend = rzg2l_irqc_irq_suspend,
|
||||
.resume = rzg2l_irqc_irq_resume,
|
||||
};
|
||||
|
||||
static const struct irq_chip irqc_chip = {
|
||||
.name = "rzg2l-irqc",
|
||||
.irq_eoi = rzg2l_irqc_eoi,
|
||||
@@ -357,13 +409,12 @@ static int rzg2l_irqc_parse_interrupts(struct rzg2l_irqc_priv *priv,
|
||||
|
||||
static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
|
||||
{
|
||||
struct platform_device *pdev = of_find_device_by_node(node);
|
||||
struct device *dev __free(put_device) = pdev ? &pdev->dev : NULL;
|
||||
struct irq_domain *irq_domain, *parent_domain;
|
||||
struct platform_device *pdev;
|
||||
struct reset_control *resetn;
|
||||
struct rzg2l_irqc_priv *priv;
|
||||
int ret;
|
||||
|
||||
pdev = of_find_device_by_node(node);
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
@@ -373,15 +424,15 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
rzg2l_irqc_data = devm_kzalloc(&pdev->dev, sizeof(*rzg2l_irqc_data), GFP_KERNEL);
|
||||
if (!rzg2l_irqc_data)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
rzg2l_irqc_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
|
||||
if (IS_ERR(rzg2l_irqc_data->base))
|
||||
return PTR_ERR(rzg2l_irqc_data->base);
|
||||
|
||||
ret = rzg2l_irqc_parse_interrupts(priv, node);
|
||||
ret = rzg2l_irqc_parse_interrupts(rzg2l_irqc_data, node);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
|
||||
return ret;
|
||||
@@ -404,17 +455,30 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
|
||||
goto pm_disable;
|
||||
}
|
||||
|
||||
raw_spin_lock_init(&priv->lock);
|
||||
raw_spin_lock_init(&rzg2l_irqc_data->lock);
|
||||
|
||||
irq_domain = irq_domain_add_hierarchy(parent_domain, 0, IRQC_NUM_IRQ,
|
||||
node, &rzg2l_irqc_domain_ops,
|
||||
priv);
|
||||
rzg2l_irqc_data);
|
||||
if (!irq_domain) {
|
||||
dev_err(&pdev->dev, "failed to add irq domain\n");
|
||||
ret = -ENOMEM;
|
||||
goto pm_put;
|
||||
}
|
||||
|
||||
register_syscore_ops(&rzg2l_irqc_syscore_ops);
|
||||
|
||||
/*
|
||||
* Prevent the cleanup function from invoking put_device by assigning
|
||||
* NULL to dev.
|
||||
*
|
||||
* make coccicheck will complain about missing put_device calls, but
|
||||
* those are false positives, as dev will be automatically "put" via
|
||||
* __free_put_device on the failing path.
|
||||
* On the successful path we don't actually want to "put" dev.
|
||||
*/
|
||||
dev = NULL;
|
||||
|
||||
return 0;
|
||||
|
||||
pm_put:
|
||||
|
||||
@@ -1728,6 +1728,7 @@ int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,
|
||||
ptr = shift / 8;
|
||||
shift %= 8;
|
||||
mask >>= ptr * 8;
|
||||
ptr <<= 8;
|
||||
|
||||
err = mv88e6393x_port_policy_read(chip, port, ptr, ®);
|
||||
if (err)
|
||||
|
||||
@@ -484,7 +484,7 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
if (unlikely(skb->len > MAX_FRAME_SIZE)) {
|
||||
dev->stats.tx_errors++;
|
||||
goto out;
|
||||
goto len_error;
|
||||
}
|
||||
|
||||
/* Save skb pointer. */
|
||||
@@ -575,6 +575,7 @@ frag_map_error:
|
||||
map_error:
|
||||
if (net_ratelimit())
|
||||
dev_warn(greth->dev, "Could not create TX DMA mapping\n");
|
||||
len_error:
|
||||
dev_kfree_skb(skb);
|
||||
out:
|
||||
return err;
|
||||
|
||||
@@ -1348,6 +1348,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
|
||||
netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n",
|
||||
skb->data, skb_len);
|
||||
ret = NETDEV_TX_OK;
|
||||
dev_kfree_skb_any(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -1382,10 +1382,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
be_get_wrb_params_from_skb(adapter, skb, &wrb_params);
|
||||
|
||||
wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params);
|
||||
if (unlikely(!wrb_cnt)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
goto drop;
|
||||
}
|
||||
if (unlikely(!wrb_cnt))
|
||||
goto drop_skb;
|
||||
|
||||
/* if os2bmc is enabled and if the pkt is destined to bmc,
|
||||
* enqueue the pkt a 2nd time with mgmt bit set.
|
||||
@@ -1394,7 +1392,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
BE_WRB_F_SET(wrb_params.features, OS2BMC, 1);
|
||||
wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params);
|
||||
if (unlikely(!wrb_cnt))
|
||||
goto drop;
|
||||
goto drop_skb;
|
||||
else
|
||||
skb_get(skb);
|
||||
}
|
||||
@@ -1408,6 +1406,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
be_xmit_flush(adapter, txo);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
drop_skb:
|
||||
dev_kfree_skb_any(skb);
|
||||
drop:
|
||||
tx_stats(txo)->tx_drv_drops++;
|
||||
/* Flush the already enqueued tx requests */
|
||||
|
||||
@@ -1011,6 +1011,7 @@ sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
|
||||
if(skb->len > XMIT_BUFF_SIZE)
|
||||
{
|
||||
printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
|
||||
dev_kfree_skb(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -336,6 +336,51 @@ static int octep_oq_check_hw_for_pkts(struct octep_device *oct,
|
||||
return new_pkts;
|
||||
}
|
||||
|
||||
/**
|
||||
* octep_oq_next_pkt() - Move to the next packet in Rx queue.
|
||||
*
|
||||
* @oq: Octeon Rx queue data structure.
|
||||
* @buff_info: Current packet buffer info.
|
||||
* @read_idx: Current packet index in the ring.
|
||||
* @desc_used: Current packet descriptor number.
|
||||
*
|
||||
* Free the resources associated with a packet.
|
||||
* Increment packet index in the ring and packet descriptor number.
|
||||
*/
|
||||
static void octep_oq_next_pkt(struct octep_oq *oq,
|
||||
struct octep_rx_buffer *buff_info,
|
||||
u32 *read_idx, u32 *desc_used)
|
||||
{
|
||||
dma_unmap_page(oq->dev, oq->desc_ring[*read_idx].buffer_ptr,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
buff_info->page = NULL;
|
||||
(*read_idx)++;
|
||||
(*desc_used)++;
|
||||
if (*read_idx == oq->max_count)
|
||||
*read_idx = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* octep_oq_drop_rx() - Free the resources associated with a packet.
|
||||
*
|
||||
* @oq: Octeon Rx queue data structure.
|
||||
* @buff_info: Current packet buffer info.
|
||||
* @read_idx: Current packet index in the ring.
|
||||
* @desc_used: Current packet descriptor number.
|
||||
*
|
||||
*/
|
||||
static void octep_oq_drop_rx(struct octep_oq *oq,
|
||||
struct octep_rx_buffer *buff_info,
|
||||
u32 *read_idx, u32 *desc_used)
|
||||
{
|
||||
int data_len = buff_info->len - oq->max_single_buffer_size;
|
||||
|
||||
while (data_len > 0) {
|
||||
octep_oq_next_pkt(oq, buff_info, read_idx, desc_used);
|
||||
data_len -= oq->buffer_size;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* __octep_oq_process_rx() - Process hardware Rx queue and push to stack.
|
||||
*
|
||||
@@ -365,10 +410,7 @@ static int __octep_oq_process_rx(struct octep_device *oct,
|
||||
desc_used = 0;
|
||||
for (pkt = 0; pkt < pkts_to_process; pkt++) {
|
||||
buff_info = (struct octep_rx_buffer *)&oq->buff_info[read_idx];
|
||||
dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
resp_hw = page_address(buff_info->page);
|
||||
buff_info->page = NULL;
|
||||
|
||||
/* Swap the length field that is in Big-Endian to CPU */
|
||||
buff_info->len = be64_to_cpu(resp_hw->length);
|
||||
@@ -390,36 +432,33 @@ static int __octep_oq_process_rx(struct octep_device *oct,
|
||||
*/
|
||||
data_offset = OCTEP_OQ_RESP_HW_SIZE;
|
||||
}
|
||||
|
||||
octep_oq_next_pkt(oq, buff_info, &read_idx, &desc_used);
|
||||
|
||||
skb = build_skb((void *)resp_hw, PAGE_SIZE);
|
||||
if (!skb) {
|
||||
octep_oq_drop_rx(oq, buff_info,
|
||||
&read_idx, &desc_used);
|
||||
oq->stats.alloc_failures++;
|
||||
continue;
|
||||
}
|
||||
skb_reserve(skb, data_offset);
|
||||
|
||||
rx_bytes += buff_info->len;
|
||||
|
||||
if (buff_info->len <= oq->max_single_buffer_size) {
|
||||
skb = build_skb((void *)resp_hw, PAGE_SIZE);
|
||||
skb_reserve(skb, data_offset);
|
||||
skb_put(skb, buff_info->len);
|
||||
read_idx++;
|
||||
desc_used++;
|
||||
if (read_idx == oq->max_count)
|
||||
read_idx = 0;
|
||||
} else {
|
||||
struct skb_shared_info *shinfo;
|
||||
u16 data_len;
|
||||
|
||||
skb = build_skb((void *)resp_hw, PAGE_SIZE);
|
||||
skb_reserve(skb, data_offset);
|
||||
/* Head fragment includes response header(s);
|
||||
* subsequent fragments contains only data.
|
||||
*/
|
||||
skb_put(skb, oq->max_single_buffer_size);
|
||||
read_idx++;
|
||||
desc_used++;
|
||||
if (read_idx == oq->max_count)
|
||||
read_idx = 0;
|
||||
|
||||
shinfo = skb_shinfo(skb);
|
||||
data_len = buff_info->len - oq->max_single_buffer_size;
|
||||
while (data_len) {
|
||||
dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
buff_info = (struct octep_rx_buffer *)
|
||||
&oq->buff_info[read_idx];
|
||||
if (data_len < oq->buffer_size) {
|
||||
@@ -434,11 +473,8 @@ static int __octep_oq_process_rx(struct octep_device *oct,
|
||||
buff_info->page, 0,
|
||||
buff_info->len,
|
||||
buff_info->len);
|
||||
buff_info->page = NULL;
|
||||
read_idx++;
|
||||
desc_used++;
|
||||
if (read_idx == oq->max_count)
|
||||
read_idx = 0;
|
||||
|
||||
octep_oq_next_pkt(oq, buff_info, &read_idx, &desc_used);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2279,7 +2279,7 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link));
|
||||
if (!(cfg & BIT_ULL(12)))
|
||||
continue;
|
||||
bmap |= (1 << i);
|
||||
bmap |= BIT_ULL(i);
|
||||
cfg &= ~BIT_ULL(12);
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link), cfg);
|
||||
@@ -2300,7 +2300,7 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
|
||||
|
||||
/* Set NIX_AF_TL3_TL2_LINKX_CFG[ENA] for the TL3/TL2 queue */
|
||||
for (i = 0; i < (rvu->hw->cgx_links + rvu->hw->lbk_links); i++) {
|
||||
if (!(bmap & (1 << i)))
|
||||
if (!(bmap & BIT_ULL(i)))
|
||||
continue;
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link));
|
||||
|
||||
@@ -1570,7 +1570,6 @@ static void clean_debug_files(struct mlx5_core_dev *dev)
|
||||
if (!mlx5_debugfs_root)
|
||||
return;
|
||||
|
||||
mlx5_cmdif_debugfs_cleanup(dev);
|
||||
debugfs_remove_recursive(dbg->dbg_root);
|
||||
}
|
||||
|
||||
@@ -1585,8 +1584,6 @@ static void create_debugfs_files(struct mlx5_core_dev *dev)
|
||||
debugfs_create_file("out_len", 0600, dbg->dbg_root, dev, &olfops);
|
||||
debugfs_create_u8("status", 0600, dbg->dbg_root, &dbg->status);
|
||||
debugfs_create_file("run", 0200, dbg->dbg_root, dev, &fops);
|
||||
|
||||
mlx5_cmdif_debugfs_init(dev);
|
||||
}
|
||||
|
||||
void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode)
|
||||
@@ -1758,6 +1755,10 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
|
||||
}
|
||||
}
|
||||
|
||||
#define MLX5_MAX_MANAGE_PAGES_CMD_ENT 1
|
||||
#define MLX5_CMD_MASK ((1UL << (cmd->vars.max_reg_cmds + \
|
||||
MLX5_MAX_MANAGE_PAGES_CMD_ENT)) - 1)
|
||||
|
||||
static void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_cmd *cmd = &dev->cmd;
|
||||
@@ -1769,7 +1770,7 @@ static void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev)
|
||||
/* wait for pending handlers to complete */
|
||||
mlx5_eq_synchronize_cmd_irq(dev);
|
||||
spin_lock_irqsave(&dev->cmd.alloc_lock, flags);
|
||||
vector = ~dev->cmd.vars.bitmask & ((1ul << (1 << dev->cmd.vars.log_sz)) - 1);
|
||||
vector = ~dev->cmd.vars.bitmask & MLX5_CMD_MASK;
|
||||
if (!vector)
|
||||
goto no_trig;
|
||||
|
||||
@@ -2215,20 +2216,10 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
||||
int size = sizeof(struct mlx5_cmd_prot_block);
|
||||
int align = roundup_pow_of_two(size);
|
||||
struct mlx5_cmd *cmd = &dev->cmd;
|
||||
u32 cmd_h, cmd_l;
|
||||
u16 cmd_if_rev;
|
||||
u32 cmd_l;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd_if_rev = cmdif_rev(dev);
|
||||
if (cmd_if_rev != CMD_IF_REV) {
|
||||
mlx5_core_err(dev,
|
||||
"Driver cmdif rev(%d) differs from firmware's(%d)\n",
|
||||
CMD_IF_REV, cmd_if_rev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0);
|
||||
if (!cmd->pool)
|
||||
return -ENOMEM;
|
||||
@@ -2237,39 +2228,84 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
||||
if (err)
|
||||
goto err_free_pool;
|
||||
|
||||
cmd_l = (u32)(cmd->dma);
|
||||
if (cmd_l & 0xfff) {
|
||||
mlx5_core_err(dev, "invalid command queue address\n");
|
||||
err = -ENOMEM;
|
||||
goto err_cmd_page;
|
||||
}
|
||||
cmd->checksum_disabled = 1;
|
||||
|
||||
spin_lock_init(&cmd->alloc_lock);
|
||||
spin_lock_init(&cmd->token_lock);
|
||||
for (i = 0; i < MLX5_CMD_OP_MAX; i++)
|
||||
spin_lock_init(&cmd->stats[i].lock);
|
||||
|
||||
create_msg_cache(dev);
|
||||
|
||||
set_wqname(dev);
|
||||
cmd->wq = create_singlethread_workqueue(cmd->wq_name);
|
||||
if (!cmd->wq) {
|
||||
mlx5_core_err(dev, "failed to create command workqueue\n");
|
||||
err = -ENOMEM;
|
||||
goto err_cache;
|
||||
}
|
||||
|
||||
mlx5_cmdif_debugfs_init(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_cache:
|
||||
destroy_msg_cache(dev);
|
||||
err_cmd_page:
|
||||
free_cmd_page(dev, cmd);
|
||||
err_free_pool:
|
||||
dma_pool_destroy(cmd->pool);
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5_cmd_cleanup(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_cmd *cmd = &dev->cmd;
|
||||
|
||||
mlx5_cmdif_debugfs_cleanup(dev);
|
||||
destroy_workqueue(cmd->wq);
|
||||
destroy_msg_cache(dev);
|
||||
free_cmd_page(dev, cmd);
|
||||
dma_pool_destroy(cmd->pool);
|
||||
}
|
||||
|
||||
int mlx5_cmd_enable(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_cmd *cmd = &dev->cmd;
|
||||
u32 cmd_h, cmd_l;
|
||||
|
||||
memset(&cmd->vars, 0, sizeof(cmd->vars));
|
||||
cmd->vars.cmdif_rev = cmdif_rev(dev);
|
||||
if (cmd->vars.cmdif_rev != CMD_IF_REV) {
|
||||
mlx5_core_err(dev,
|
||||
"Driver cmdif rev(%d) differs from firmware's(%d)\n",
|
||||
CMD_IF_REV, cmd->vars.cmdif_rev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd_l = ioread32be(&dev->iseg->cmdq_addr_l_sz) & 0xff;
|
||||
cmd->vars.log_sz = cmd_l >> 4 & 0xf;
|
||||
cmd->vars.log_stride = cmd_l & 0xf;
|
||||
if (1 << cmd->vars.log_sz > MLX5_MAX_COMMANDS) {
|
||||
mlx5_core_err(dev, "firmware reports too many outstanding commands %d\n",
|
||||
1 << cmd->vars.log_sz);
|
||||
err = -EINVAL;
|
||||
goto err_free_page;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cmd->vars.log_sz + cmd->vars.log_stride > MLX5_ADAPTER_PAGE_SHIFT) {
|
||||
mlx5_core_err(dev, "command queue size overflow\n");
|
||||
err = -EINVAL;
|
||||
goto err_free_page;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd->state = MLX5_CMDIF_STATE_DOWN;
|
||||
cmd->checksum_disabled = 1;
|
||||
cmd->vars.max_reg_cmds = (1 << cmd->vars.log_sz) - 1;
|
||||
cmd->vars.bitmask = (1UL << cmd->vars.max_reg_cmds) - 1;
|
||||
|
||||
cmd->vars.cmdif_rev = ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16;
|
||||
if (cmd->vars.cmdif_rev > CMD_IF_REV) {
|
||||
mlx5_core_err(dev, "driver does not support command interface version. driver %d, firmware %d\n",
|
||||
CMD_IF_REV, cmd->vars.cmdif_rev);
|
||||
err = -EOPNOTSUPP;
|
||||
goto err_free_page;
|
||||
}
|
||||
|
||||
spin_lock_init(&cmd->alloc_lock);
|
||||
spin_lock_init(&cmd->token_lock);
|
||||
for (i = 0; i < MLX5_CMD_OP_MAX; i++)
|
||||
spin_lock_init(&cmd->stats[i].lock);
|
||||
cmd->vars.bitmask = MLX5_CMD_MASK;
|
||||
|
||||
sema_init(&cmd->vars.sem, cmd->vars.max_reg_cmds);
|
||||
sema_init(&cmd->vars.pages_sem, 1);
|
||||
@@ -2277,11 +2313,8 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
||||
|
||||
cmd_h = (u32)((u64)(cmd->dma) >> 32);
|
||||
cmd_l = (u32)(cmd->dma);
|
||||
if (cmd_l & 0xfff) {
|
||||
mlx5_core_err(dev, "invalid command queue address\n");
|
||||
err = -ENOMEM;
|
||||
goto err_free_page;
|
||||
}
|
||||
if (WARN_ON(cmd_l & 0xfff))
|
||||
return -EINVAL;
|
||||
|
||||
iowrite32be(cmd_h, &dev->iseg->cmdq_addr_h);
|
||||
iowrite32be(cmd_l, &dev->iseg->cmdq_addr_l_sz);
|
||||
@@ -2294,40 +2327,17 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
||||
cmd->mode = CMD_MODE_POLLING;
|
||||
cmd->allowed_opcode = CMD_ALLOWED_OPCODE_ALL;
|
||||
|
||||
create_msg_cache(dev);
|
||||
|
||||
set_wqname(dev);
|
||||
cmd->wq = create_singlethread_workqueue(cmd->wq_name);
|
||||
if (!cmd->wq) {
|
||||
mlx5_core_err(dev, "failed to create command workqueue\n");
|
||||
err = -ENOMEM;
|
||||
goto err_cache;
|
||||
}
|
||||
|
||||
create_debugfs_files(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_cache:
|
||||
destroy_msg_cache(dev);
|
||||
|
||||
err_free_page:
|
||||
free_cmd_page(dev, cmd);
|
||||
|
||||
err_free_pool:
|
||||
dma_pool_destroy(cmd->pool);
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5_cmd_cleanup(struct mlx5_core_dev *dev)
|
||||
void mlx5_cmd_disable(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_cmd *cmd = &dev->cmd;
|
||||
|
||||
clean_debug_files(dev);
|
||||
destroy_workqueue(cmd->wq);
|
||||
destroy_msg_cache(dev);
|
||||
free_cmd_page(dev, cmd);
|
||||
dma_pool_destroy(cmd->pool);
|
||||
flush_workqueue(cmd->wq);
|
||||
}
|
||||
|
||||
void mlx5_cmd_set_state(struct mlx5_core_dev *dev,
|
||||
|
||||
@@ -1279,7 +1279,7 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto abort;
|
||||
goto err_esw_enable;
|
||||
|
||||
esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED;
|
||||
|
||||
@@ -1293,7 +1293,8 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
|
||||
|
||||
return 0;
|
||||
|
||||
abort:
|
||||
err_esw_enable:
|
||||
mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
|
||||
mlx5_esw_acls_ns_cleanup(esw);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1114,7 +1114,7 @@ static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeou
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mlx5_cmd_init(dev);
|
||||
err = mlx5_cmd_enable(dev);
|
||||
if (err) {
|
||||
mlx5_core_err(dev, "Failed initializing command interface, aborting\n");
|
||||
return err;
|
||||
@@ -1168,7 +1168,7 @@ stop_health_poll:
|
||||
mlx5_stop_health_poll(dev, boot);
|
||||
err_cmd_cleanup:
|
||||
mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
|
||||
mlx5_cmd_cleanup(dev);
|
||||
mlx5_cmd_disable(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1179,7 +1179,7 @@ static void mlx5_function_disable(struct mlx5_core_dev *dev, bool boot)
|
||||
mlx5_core_disable_hca(dev, 0);
|
||||
mlx5_stop_health_poll(dev, boot);
|
||||
mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
|
||||
mlx5_cmd_cleanup(dev);
|
||||
mlx5_cmd_disable(dev);
|
||||
}
|
||||
|
||||
static int mlx5_function_open(struct mlx5_core_dev *dev)
|
||||
@@ -1644,6 +1644,12 @@ int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)
|
||||
mlx5_debugfs_root);
|
||||
INIT_LIST_HEAD(&priv->traps);
|
||||
|
||||
err = mlx5_cmd_init(dev);
|
||||
if (err) {
|
||||
mlx5_core_err(dev, "Failed initializing cmdif SW structs, aborting\n");
|
||||
goto err_cmd_init;
|
||||
}
|
||||
|
||||
err = mlx5_tout_init(dev);
|
||||
if (err) {
|
||||
mlx5_core_err(dev, "Failed initializing timeouts, aborting\n");
|
||||
@@ -1689,6 +1695,8 @@ err_pagealloc_init:
|
||||
err_health_init:
|
||||
mlx5_tout_cleanup(dev);
|
||||
err_timeout_init:
|
||||
mlx5_cmd_cleanup(dev);
|
||||
err_cmd_init:
|
||||
debugfs_remove(dev->priv.dbg.dbg_root);
|
||||
mutex_destroy(&priv->pgdir_mutex);
|
||||
mutex_destroy(&priv->alloc_mutex);
|
||||
@@ -1711,6 +1719,7 @@ void mlx5_mdev_uninit(struct mlx5_core_dev *dev)
|
||||
mlx5_pagealloc_cleanup(dev);
|
||||
mlx5_health_cleanup(dev);
|
||||
mlx5_tout_cleanup(dev);
|
||||
mlx5_cmd_cleanup(dev);
|
||||
debugfs_remove_recursive(dev->priv.dbg.dbg_root);
|
||||
mutex_destroy(&priv->pgdir_mutex);
|
||||
mutex_destroy(&priv->alloc_mutex);
|
||||
|
||||
@@ -177,6 +177,8 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev);
|
||||
int mlx5_query_board_id(struct mlx5_core_dev *dev);
|
||||
int mlx5_cmd_init(struct mlx5_core_dev *dev);
|
||||
void mlx5_cmd_cleanup(struct mlx5_core_dev *dev);
|
||||
int mlx5_cmd_enable(struct mlx5_core_dev *dev);
|
||||
void mlx5_cmd_disable(struct mlx5_core_dev *dev);
|
||||
void mlx5_cmd_set_state(struct mlx5_core_dev *dev,
|
||||
enum mlx5_cmdif_state cmdif_state);
|
||||
int mlx5_cmd_init_hca(struct mlx5_core_dev *dev, uint32_t *sw_owner_id);
|
||||
|
||||
@@ -4617,7 +4617,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
|
||||
if ((status & 0xffff) == 0xffff || !(status & tp->irq_mask))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (unlikely(status & SYSErr)) {
|
||||
/* At least RTL8168fp may unexpectedly set the SYSErr bit */
|
||||
if (unlikely(status & SYSErr &&
|
||||
tp->mac_version <= RTL_GIGA_MAC_VER_06)) {
|
||||
rtl8169_pcierr_interrupt(tp->dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1689,20 +1689,19 @@ static int ravb_get_ts_info(struct net_device *ndev,
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *hw_info = priv->info;
|
||||
|
||||
info->so_timestamping =
|
||||
SOF_TIMESTAMPING_TX_SOFTWARE |
|
||||
SOF_TIMESTAMPING_RX_SOFTWARE |
|
||||
SOF_TIMESTAMPING_SOFTWARE |
|
||||
SOF_TIMESTAMPING_TX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RAW_HARDWARE;
|
||||
info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
|
||||
info->rx_filters =
|
||||
(1 << HWTSTAMP_FILTER_NONE) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_ALL);
|
||||
if (hw_info->gptp || hw_info->ccc_gac)
|
||||
if (hw_info->gptp || hw_info->ccc_gac) {
|
||||
info->so_timestamping =
|
||||
SOF_TIMESTAMPING_TX_SOFTWARE |
|
||||
SOF_TIMESTAMPING_TX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RAW_HARDWARE;
|
||||
info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
|
||||
info->rx_filters =
|
||||
(1 << HWTSTAMP_FILTER_NONE) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_ALL);
|
||||
info->phc_index = ptp_clock_index(priv->ptp.clock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -844,6 +844,7 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
if (net_ratelimit())
|
||||
netdev_err(ndev, "TX DMA mapping error\n");
|
||||
ndev->stats.tx_dropped++;
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
desc_set_phys_addr(lp, phys, cur_p);
|
||||
@@ -864,6 +865,7 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
ndev->stats.tx_dropped++;
|
||||
axienet_free_tx_chain(lp, orig_tail_ptr, ii + 1,
|
||||
true, NULL, 0);
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
desc_set_phys_addr(lp, phys, cur_p);
|
||||
|
||||
@@ -2791,6 +2791,31 @@ static struct hv_driver netvsc_drv = {
|
||||
},
|
||||
};
|
||||
|
||||
/* Set VF's namespace same as the synthetic NIC */
|
||||
static void netvsc_event_set_vf_ns(struct net_device *ndev)
|
||||
{
|
||||
struct net_device_context *ndev_ctx = netdev_priv(ndev);
|
||||
struct net_device *vf_netdev;
|
||||
int ret;
|
||||
|
||||
vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
|
||||
if (!vf_netdev)
|
||||
return;
|
||||
|
||||
if (!net_eq(dev_net(ndev), dev_net(vf_netdev))) {
|
||||
ret = dev_change_net_namespace(vf_netdev, dev_net(ndev),
|
||||
"eth%d");
|
||||
if (ret)
|
||||
netdev_err(vf_netdev,
|
||||
"Cannot move to same namespace as %s: %d\n",
|
||||
ndev->name, ret);
|
||||
else
|
||||
netdev_info(vf_netdev,
|
||||
"Moved VF to namespace with: %s\n",
|
||||
ndev->name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* On Hyper-V, every VF interface is matched with a corresponding
|
||||
* synthetic interface. The synthetic interface is presented first
|
||||
@@ -2803,6 +2828,11 @@ static int netvsc_netdev_event(struct notifier_block *this,
|
||||
struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
|
||||
int ret = 0;
|
||||
|
||||
if (event_dev->netdev_ops == &device_ops && event == NETDEV_REGISTER) {
|
||||
netvsc_event_set_vf_ns(event_dev);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
ret = check_dev_is_matching_vf(event_dev);
|
||||
if (ret != 0)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
@@ -151,19 +151,6 @@ static struct macsec_rx_sa *macsec_rxsa_get(struct macsec_rx_sa __rcu *ptr)
|
||||
return sa;
|
||||
}
|
||||
|
||||
static struct macsec_rx_sa *macsec_active_rxsa_get(struct macsec_rx_sc *rx_sc)
|
||||
{
|
||||
struct macsec_rx_sa *sa = NULL;
|
||||
int an;
|
||||
|
||||
for (an = 0; an < MACSEC_NUM_AN; an++) {
|
||||
sa = macsec_rxsa_get(rx_sc->sa[an]);
|
||||
if (sa)
|
||||
break;
|
||||
}
|
||||
return sa;
|
||||
}
|
||||
|
||||
static void free_rx_sc_rcu(struct rcu_head *head)
|
||||
{
|
||||
struct macsec_rx_sc *rx_sc = container_of(head, struct macsec_rx_sc, rcu_head);
|
||||
@@ -1180,15 +1167,12 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
|
||||
/* If validateFrames is Strict or the C bit in the
|
||||
* SecTAG is set, discard
|
||||
*/
|
||||
struct macsec_rx_sa *active_rx_sa = macsec_active_rxsa_get(rx_sc);
|
||||
if (hdr->tci_an & MACSEC_TCI_C ||
|
||||
secy->validate_frames == MACSEC_VALIDATE_STRICT) {
|
||||
u64_stats_update_begin(&rxsc_stats->syncp);
|
||||
rxsc_stats->stats.InPktsNotUsingSA++;
|
||||
u64_stats_update_end(&rxsc_stats->syncp);
|
||||
DEV_STATS_INC(secy->netdev, rx_errors);
|
||||
if (active_rx_sa)
|
||||
this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA);
|
||||
goto drop_nosa;
|
||||
}
|
||||
|
||||
@@ -1198,8 +1182,6 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
|
||||
u64_stats_update_begin(&rxsc_stats->syncp);
|
||||
rxsc_stats->stats.InPktsUnusedSA++;
|
||||
u64_stats_update_end(&rxsc_stats->syncp);
|
||||
if (active_rx_sa)
|
||||
this_cpu_inc(active_rx_sa->stats->InPktsUnusedSA);
|
||||
goto deliver;
|
||||
}
|
||||
|
||||
|
||||
@@ -836,7 +836,8 @@ static void nsim_dev_trap_report_work(struct work_struct *work)
|
||||
nsim_dev = nsim_trap_data->nsim_dev;
|
||||
|
||||
if (!devl_trylock(priv_to_devlink(nsim_dev))) {
|
||||
schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 1);
|
||||
queue_delayed_work(system_unbound_wq,
|
||||
&nsim_dev->trap_data->trap_report_dw, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -848,11 +849,12 @@ static void nsim_dev_trap_report_work(struct work_struct *work)
|
||||
continue;
|
||||
|
||||
nsim_dev_trap_report(nsim_dev_port);
|
||||
cond_resched();
|
||||
}
|
||||
devl_unlock(priv_to_devlink(nsim_dev));
|
||||
|
||||
schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw,
|
||||
msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
|
||||
queue_delayed_work(system_unbound_wq,
|
||||
&nsim_dev->trap_data->trap_report_dw,
|
||||
msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
|
||||
}
|
||||
|
||||
static int nsim_dev_traps_init(struct devlink *devlink)
|
||||
@@ -907,8 +909,9 @@ static int nsim_dev_traps_init(struct devlink *devlink)
|
||||
|
||||
INIT_DELAYED_WORK(&nsim_dev->trap_data->trap_report_dw,
|
||||
nsim_dev_trap_report_work);
|
||||
schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw,
|
||||
msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
|
||||
queue_delayed_work(system_unbound_wq,
|
||||
&nsim_dev->trap_data->trap_report_dw,
|
||||
msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
/* Control Register 2 bits */
|
||||
#define DP83822_FX_ENABLE BIT(14)
|
||||
|
||||
#define DP83822_HW_RESET BIT(15)
|
||||
#define DP83822_SW_RESET BIT(14)
|
||||
#define DP83822_SW_RESET BIT(15)
|
||||
#define DP83822_DIG_RESTART BIT(14)
|
||||
|
||||
/* PHY STS bits */
|
||||
#define DP83822_PHYSTS_DUPLEX BIT(2)
|
||||
|
||||
@@ -815,7 +815,7 @@ plip_send_packet(struct net_device *dev, struct net_local *nl,
|
||||
return HS_TIMEOUT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
fallthrough;
|
||||
|
||||
case PLIP_PK_LENGTH_LSB:
|
||||
if (plip_send(nibble_timeout, dev,
|
||||
|
||||
@@ -1766,7 +1766,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
|
||||
// can rename the link if it knows better.
|
||||
if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
|
||||
((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 ||
|
||||
(net->dev_addr [0] & 0x02) == 0))
|
||||
/* somebody touched it*/
|
||||
!is_zero_ether_addr(net->dev_addr)))
|
||||
strscpy(net->name, "eth%d", sizeof(net->name));
|
||||
/* WLAN devices should always be named "wlan%d" */
|
||||
if ((dev->driver_info->flags & FLAG_WLAN) != 0)
|
||||
@@ -1869,6 +1870,7 @@ out1:
|
||||
* may trigger an error resubmitting itself and, worse,
|
||||
* schedule a timer. So we kill it all just in case.
|
||||
*/
|
||||
usbnet_mark_going_away(dev);
|
||||
cancel_work_sync(&dev->kevent);
|
||||
del_timer_sync(&dev->delay);
|
||||
free_percpu(net->tstats);
|
||||
|
||||
@@ -994,7 +994,7 @@ static const struct nla_policy wwan_rtnl_policy[IFLA_WWAN_MAX + 1] = {
|
||||
|
||||
static struct rtnl_link_ops wwan_rtnl_link_ops __read_mostly = {
|
||||
.kind = "wwan",
|
||||
.maxtype = __IFLA_WWAN_MAX,
|
||||
.maxtype = IFLA_WWAN_MAX,
|
||||
.alloc = wwan_rtnl_alloc,
|
||||
.validate = wwan_rtnl_validate,
|
||||
.newlink = wwan_rtnl_newlink,
|
||||
|
||||
@@ -264,6 +264,15 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = {
|
||||
/*Speaker Mute*/
|
||||
{ KE_KEY, 0x109, { KEY_MUTE} },
|
||||
|
||||
/* S2Idle screen off */
|
||||
{ KE_IGNORE, 0x120, { KEY_RESERVED }},
|
||||
|
||||
/* Leaving S4 or S2Idle suspend */
|
||||
{ KE_IGNORE, 0x130, { KEY_RESERVED }},
|
||||
|
||||
/* Entering S2Idle suspend */
|
||||
{ KE_IGNORE, 0x140, { KEY_RESERVED }},
|
||||
|
||||
/* Mic mute */
|
||||
{ KE_KEY, 0x150, { KEY_MICMUTE } },
|
||||
|
||||
|
||||
@@ -524,6 +524,7 @@ static int __init sysman_init(void)
|
||||
int ret = 0;
|
||||
|
||||
if (!dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL) &&
|
||||
!dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Alienware", NULL) &&
|
||||
!dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "www.dell.com", NULL)) {
|
||||
pr_err("Unable to run on non-Dell system\n");
|
||||
return -ENODEV;
|
||||
|
||||
@@ -166,7 +166,7 @@ static int __dtpm_devfreq_setup(struct devfreq *devfreq, struct dtpm *parent)
|
||||
ret = dev_pm_qos_add_request(dev, &dtpm_devfreq->qos_req,
|
||||
DEV_PM_QOS_MAX_FREQUENCY,
|
||||
PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
pr_err("Failed to add QoS request: %d\n", ret);
|
||||
goto out_dtpm_unregister;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/pps_kernel.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status)
|
||||
static void pps_tty_dcd_change(struct tty_struct *tty, bool active)
|
||||
{
|
||||
struct pps_device *pps;
|
||||
struct pps_event_time ts;
|
||||
@@ -29,11 +29,11 @@ static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status)
|
||||
return;
|
||||
|
||||
/* Now do the PPS event report */
|
||||
pps_event(pps, &ts, status ? PPS_CAPTUREASSERT :
|
||||
pps_event(pps, &ts, active ? PPS_CAPTUREASSERT :
|
||||
PPS_CAPTURECLEAR, NULL);
|
||||
|
||||
dev_dbg(pps->dev, "PPS %s at %lu\n",
|
||||
status ? "assert" : "clear", jiffies);
|
||||
active ? "assert" : "clear", jiffies);
|
||||
}
|
||||
|
||||
static int (*alias_n_tty_open)(struct tty_struct *tty);
|
||||
|
||||
@@ -733,7 +733,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
||||
|
||||
dev->queues = kcalloc(nr_cpu_ids, sizeof(*dev->queues), GFP_KERNEL);
|
||||
if (!dev->queues) {
|
||||
dev->transport->free_device(dev);
|
||||
hba->backend->ops->free_device(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -2130,7 +2130,7 @@ static int tcmu_netlink_event_send(struct tcmu_dev *udev,
|
||||
}
|
||||
|
||||
ret = genlmsg_multicast_allns(&tcmu_genl_family, skb, 0,
|
||||
TCMU_MCGRP_CONFIG, GFP_KERNEL);
|
||||
TCMU_MCGRP_CONFIG);
|
||||
|
||||
/* Wait during an add as the listener may not be up yet */
|
||||
if (ret == 0 ||
|
||||
|
||||
@@ -801,7 +801,22 @@ static irqreturn_t __imx_uart_rtsint(int irq, void *dev_id)
|
||||
|
||||
imx_uart_writel(sport, USR1_RTSD, USR1);
|
||||
usr1 = imx_uart_readl(sport, USR1) & USR1_RTSS;
|
||||
uart_handle_cts_change(&sport->port, !!usr1);
|
||||
/*
|
||||
* Update sport->old_status here, so any follow-up calls to
|
||||
* imx_uart_mctrl_check() will be able to recognize that RTS
|
||||
* state changed since last imx_uart_mctrl_check() call.
|
||||
*
|
||||
* In case RTS has been detected as asserted here and later on
|
||||
* deasserted by the time imx_uart_mctrl_check() was called,
|
||||
* imx_uart_mctrl_check() can detect the RTS state change and
|
||||
* trigger uart_handle_cts_change() to unblock the port for
|
||||
* further TX transfers.
|
||||
*/
|
||||
if (usr1 & USR1_RTSS)
|
||||
sport->old_status |= TIOCM_CTS;
|
||||
else
|
||||
sport->old_status &= ~TIOCM_CTS;
|
||||
uart_handle_cts_change(&sport->port, usr1);
|
||||
wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
@@ -250,7 +250,7 @@ static int max3100_handlerx_unlocked(struct max3100_port *s, u16 rx)
|
||||
cts = (rx & MAX3100_CTS) > 0;
|
||||
if (s->cts != cts) {
|
||||
s->cts = cts;
|
||||
uart_handle_cts_change(&s->port, cts ? TIOCM_CTS : 0);
|
||||
uart_handle_cts_change(&s->port, cts);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -843,8 +843,7 @@ static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno)
|
||||
|
||||
if (ists & MAX310X_IRQ_CTS_BIT) {
|
||||
lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
||||
uart_handle_cts_change(port,
|
||||
!!(lsr & MAX310X_LSR_CTS_BIT));
|
||||
uart_handle_cts_change(port, lsr & MAX310X_LSR_CTS_BIT);
|
||||
}
|
||||
if (rxlen)
|
||||
max310x_handle_rx(port, rxlen);
|
||||
|
||||
@@ -339,14 +339,16 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
|
||||
/*
|
||||
* Turn off DTR and RTS early.
|
||||
*/
|
||||
if (uport && uart_console(uport) && tty) {
|
||||
uport->cons->cflag = tty->termios.c_cflag;
|
||||
uport->cons->ispeed = tty->termios.c_ispeed;
|
||||
uport->cons->ospeed = tty->termios.c_ospeed;
|
||||
}
|
||||
if (uport) {
|
||||
if (uart_console(uport) && tty) {
|
||||
uport->cons->cflag = tty->termios.c_cflag;
|
||||
uport->cons->ispeed = tty->termios.c_ispeed;
|
||||
uport->cons->ospeed = tty->termios.c_ospeed;
|
||||
}
|
||||
|
||||
if (!tty || C_HUPCL(tty))
|
||||
uart_port_dtr_rts(uport, 0);
|
||||
if (!tty || C_HUPCL(tty))
|
||||
uart_port_dtr_rts(uport, 0);
|
||||
}
|
||||
|
||||
uart_port_shutdown(port);
|
||||
}
|
||||
@@ -3290,11 +3292,11 @@ EXPORT_SYMBOL(uart_match_port);
|
||||
/**
|
||||
* uart_handle_dcd_change - handle a change of carrier detect state
|
||||
* @uport: uart_port structure for the open port
|
||||
* @status: new carrier detect status, nonzero if active
|
||||
* @active: new carrier detect status
|
||||
*
|
||||
* Caller must hold uport->lock.
|
||||
*/
|
||||
void uart_handle_dcd_change(struct uart_port *uport, unsigned int status)
|
||||
void uart_handle_dcd_change(struct uart_port *uport, bool active)
|
||||
{
|
||||
struct tty_port *port = &uport->state->port;
|
||||
struct tty_struct *tty = port->tty;
|
||||
@@ -3306,7 +3308,7 @@ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status)
|
||||
ld = tty_ldisc_ref(tty);
|
||||
if (ld) {
|
||||
if (ld->ops->dcd_change)
|
||||
ld->ops->dcd_change(tty, status);
|
||||
ld->ops->dcd_change(tty, active);
|
||||
tty_ldisc_deref(ld);
|
||||
}
|
||||
}
|
||||
@@ -3314,7 +3316,7 @@ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status)
|
||||
uport->icount.dcd++;
|
||||
|
||||
if (uart_dcd_enabled(uport)) {
|
||||
if (status)
|
||||
if (active)
|
||||
wake_up_interruptible(&port->open_wait);
|
||||
else if (tty)
|
||||
tty_hangup(tty);
|
||||
@@ -3325,11 +3327,11 @@ EXPORT_SYMBOL_GPL(uart_handle_dcd_change);
|
||||
/**
|
||||
* uart_handle_cts_change - handle a change of clear-to-send state
|
||||
* @uport: uart_port structure for the open port
|
||||
* @status: new clear to send status, nonzero if active
|
||||
* @active: new clear-to-send status
|
||||
*
|
||||
* Caller must hold uport->lock.
|
||||
*/
|
||||
void uart_handle_cts_change(struct uart_port *uport, unsigned int status)
|
||||
void uart_handle_cts_change(struct uart_port *uport, bool active)
|
||||
{
|
||||
lockdep_assert_held_once(&uport->lock);
|
||||
|
||||
@@ -3337,13 +3339,13 @@ void uart_handle_cts_change(struct uart_port *uport, unsigned int status)
|
||||
|
||||
if (uart_softcts_mode(uport)) {
|
||||
if (uport->hw_stopped) {
|
||||
if (status) {
|
||||
if (active) {
|
||||
uport->hw_stopped = 0;
|
||||
uport->ops->start_tx(uport);
|
||||
uart_write_wakeup(uport);
|
||||
}
|
||||
} else {
|
||||
if (!status) {
|
||||
if (!active) {
|
||||
uport->hw_stopped = 1;
|
||||
uport->ops->stop_tx(uport);
|
||||
}
|
||||
|
||||
@@ -89,10 +89,10 @@ static int receive_chars_getchar(struct uart_port *port)
|
||||
|
||||
if (c == CON_HUP) {
|
||||
hung_up = 1;
|
||||
uart_handle_dcd_change(port, 0);
|
||||
uart_handle_dcd_change(port, false);
|
||||
} else if (hung_up) {
|
||||
hung_up = 0;
|
||||
uart_handle_dcd_change(port, 1);
|
||||
uart_handle_dcd_change(port, true);
|
||||
}
|
||||
|
||||
if (port->state == NULL) {
|
||||
@@ -135,7 +135,7 @@ static int receive_chars_read(struct uart_port *port)
|
||||
bytes_read = 1;
|
||||
} else if (stat == CON_HUP) {
|
||||
hung_up = 1;
|
||||
uart_handle_dcd_change(port, 0);
|
||||
uart_handle_dcd_change(port, false);
|
||||
continue;
|
||||
} else {
|
||||
/* HV_EWOULDBLOCK, etc. */
|
||||
@@ -145,7 +145,7 @@ static int receive_chars_read(struct uart_port *port)
|
||||
|
||||
if (hung_up) {
|
||||
hung_up = 0;
|
||||
uart_handle_dcd_change(port, 1);
|
||||
uart_handle_dcd_change(port, true);
|
||||
}
|
||||
|
||||
if (port->sysrq != 0 && *con_read_page) {
|
||||
|
||||
@@ -2060,6 +2060,11 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
|
||||
DWC3_GUSB2PHYCFG_SUSPHY) ||
|
||||
(dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)) &
|
||||
DWC3_GUSB3PIPECTL_SUSPHY);
|
||||
|
||||
switch (dwc->current_dr_role) {
|
||||
case DWC3_GCTL_PRTCAP_DEVICE:
|
||||
if (pm_runtime_suspended(dwc->dev))
|
||||
@@ -2107,6 +2112,15 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!PMSG_IS_AUTO(msg)) {
|
||||
/*
|
||||
* TI AM62 platform requires SUSPHY to be
|
||||
* enabled for system suspend to work.
|
||||
*/
|
||||
if (!dwc->susphy_state)
|
||||
dwc3_enable_susphy(dwc, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2169,6 +2183,11 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!PMSG_IS_AUTO(msg)) {
|
||||
/* restore SUSPHY state to that before system suspend. */
|
||||
dwc3_enable_susphy(dwc, dwc->susphy_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1131,6 +1131,8 @@ struct dwc3_scratchpad_array {
|
||||
* @dis_metastability_quirk: set to disable metastability quirk.
|
||||
* @dis_split_quirk: set to disable split boundary.
|
||||
* @suspended: set to track suspend event due to U3/L2.
|
||||
* @susphy_state: state of DWC3_GUSB2PHYCFG_SUSPHY + DWC3_GUSB3PIPECTL_SUSPHY
|
||||
* before PM suspend.
|
||||
* @imod_interval: set the interrupt moderation interval in 250ns
|
||||
* increments or 0 to disable.
|
||||
* @max_cfg_eps: current max number of IN eps used across all USB configs.
|
||||
@@ -1351,6 +1353,7 @@ struct dwc3 {
|
||||
unsigned dis_split_quirk:1;
|
||||
unsigned async_callbacks:1;
|
||||
unsigned suspended:1;
|
||||
unsigned susphy_state:1;
|
||||
|
||||
u16 imod_interval;
|
||||
|
||||
|
||||
@@ -490,6 +490,46 @@ int usb_interface_id(struct usb_configuration *config,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_interface_id);
|
||||
|
||||
/**
|
||||
* usb_func_wakeup - sends function wake notification to the host.
|
||||
* @func: function that sends the remote wakeup notification.
|
||||
*
|
||||
* Applicable to devices operating at enhanced superspeed when usb
|
||||
* functions are put in function suspend state and armed for function
|
||||
* remote wakeup. On completion, function wake notification is sent. If
|
||||
* the device is in low power state it tries to bring the device to active
|
||||
* state before sending the wake notification. Since it is a synchronous
|
||||
* call, caller must take care of not calling it in interrupt context.
|
||||
* For devices operating at lower speeds returns negative errno.
|
||||
*
|
||||
* Returns zero on success, else negative errno.
|
||||
*/
|
||||
int usb_func_wakeup(struct usb_function *func)
|
||||
{
|
||||
struct usb_gadget *gadget = func->config->cdev->gadget;
|
||||
int id;
|
||||
|
||||
if (!gadget->ops->func_wakeup)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!func->func_wakeup_armed) {
|
||||
ERROR(func->config->cdev, "not armed for func remote wakeup\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (id = 0; id < MAX_CONFIG_INTERFACES; id++)
|
||||
if (func->config->interface[id] == func)
|
||||
break;
|
||||
|
||||
if (id == MAX_CONFIG_INTERFACES) {
|
||||
ERROR(func->config->cdev, "Invalid function\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return gadget->ops->func_wakeup(gadget, id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_func_wakeup);
|
||||
|
||||
static u8 encode_bMaxPower(enum usb_device_speed speed,
|
||||
struct usb_configuration *c)
|
||||
{
|
||||
|
||||
@@ -2042,7 +2042,7 @@ static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \
|
||||
int result; \
|
||||
\
|
||||
mutex_lock(&opts->lock); \
|
||||
result = snprintf(page, sizeof(opts->name), "%s", opts->name); \
|
||||
result = scnprintf(page, sizeof(opts->name), "%s", opts->name); \
|
||||
mutex_unlock(&opts->lock); \
|
||||
\
|
||||
return result; \
|
||||
@@ -2052,7 +2052,7 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
|
||||
const char *page, size_t len) \
|
||||
{ \
|
||||
struct f_uac2_opts *opts = to_f_uac2_opts(item); \
|
||||
int ret = 0; \
|
||||
int ret = len; \
|
||||
\
|
||||
mutex_lock(&opts->lock); \
|
||||
if (opts->refcnt) { \
|
||||
@@ -2060,8 +2060,11 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
|
||||
goto end; \
|
||||
} \
|
||||
\
|
||||
ret = snprintf(opts->name, min(sizeof(opts->name), len), \
|
||||
"%s", page); \
|
||||
if (len && page[len - 1] == '\n') \
|
||||
len--; \
|
||||
\
|
||||
scnprintf(opts->name, min(sizeof(opts->name), len + 1), \
|
||||
"%s", page); \
|
||||
\
|
||||
end: \
|
||||
mutex_unlock(&opts->lock); \
|
||||
@@ -2178,7 +2181,7 @@ static struct usb_function_instance *afunc_alloc_inst(void)
|
||||
opts->req_number = UAC2_DEF_REQ_NUM;
|
||||
opts->fb_max = FBACK_FAST_MAX;
|
||||
|
||||
snprintf(opts->function_name, sizeof(opts->function_name), "Source/Sink");
|
||||
scnprintf(opts->function_name, sizeof(opts->function_name), "Source/Sink");
|
||||
|
||||
return &opts->func_inst;
|
||||
}
|
||||
|
||||
85
drivers/usb/host/xhci-caps.h
Normal file
85
drivers/usb/host/xhci-caps.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
/* hc_capbase bitmasks */
|
||||
/* bits 7:0 - how long is the Capabilities register */
|
||||
#define HC_LENGTH(p) XHCI_HC_LENGTH(p)
|
||||
/* bits 31:16 */
|
||||
#define HC_VERSION(p) (((p) >> 16) & 0xffff)
|
||||
|
||||
/* HCSPARAMS1 - hcs_params1 - bitmasks */
|
||||
/* bits 0:7, Max Device Slots */
|
||||
#define HCS_MAX_SLOTS(p) (((p) >> 0) & 0xff)
|
||||
#define HCS_SLOTS_MASK 0xff
|
||||
/* bits 8:18, Max Interrupters */
|
||||
#define HCS_MAX_INTRS(p) (((p) >> 8) & 0x7ff)
|
||||
/* bits 24:31, Max Ports - max value is 0x7F = 127 ports */
|
||||
#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f)
|
||||
|
||||
/* HCSPARAMS2 - hcs_params2 - bitmasks */
|
||||
/* bits 0:3, frames or uframes that SW needs to queue transactions
|
||||
* ahead of the HW to meet periodic deadlines */
|
||||
#define HCS_IST(p) (((p) >> 0) & 0xf)
|
||||
/* bits 4:7, max number of Event Ring segments */
|
||||
#define HCS_ERST_MAX(p) (((p) >> 4) & 0xf)
|
||||
/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */
|
||||
/* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
|
||||
/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */
|
||||
#define HCS_MAX_SCRATCHPAD(p) ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f))
|
||||
|
||||
/* HCSPARAMS3 - hcs_params3 - bitmasks */
|
||||
/* bits 0:7, Max U1 to U0 latency for the roothub ports */
|
||||
#define HCS_U1_LATENCY(p) (((p) >> 0) & 0xff)
|
||||
/* bits 16:31, Max U2 to U0 latency for the roothub ports */
|
||||
#define HCS_U2_LATENCY(p) (((p) >> 16) & 0xffff)
|
||||
|
||||
/* HCCPARAMS - hcc_params - bitmasks */
|
||||
/* true: HC can use 64-bit address pointers */
|
||||
#define HCC_64BIT_ADDR(p) ((p) & (1 << 0))
|
||||
/* true: HC can do bandwidth negotiation */
|
||||
#define HCC_BANDWIDTH_NEG(p) ((p) & (1 << 1))
|
||||
/* true: HC uses 64-byte Device Context structures
|
||||
* FIXME 64-byte context structures aren't supported yet.
|
||||
*/
|
||||
#define HCC_64BYTE_CONTEXT(p) ((p) & (1 << 2))
|
||||
/* true: HC has port power switches */
|
||||
#define HCC_PPC(p) ((p) & (1 << 3))
|
||||
/* true: HC has port indicators */
|
||||
#define HCS_INDICATOR(p) ((p) & (1 << 4))
|
||||
/* true: HC has Light HC Reset Capability */
|
||||
#define HCC_LIGHT_RESET(p) ((p) & (1 << 5))
|
||||
/* true: HC supports latency tolerance messaging */
|
||||
#define HCC_LTC(p) ((p) & (1 << 6))
|
||||
/* true: no secondary Stream ID Support */
|
||||
#define HCC_NSS(p) ((p) & (1 << 7))
|
||||
/* true: HC supports Stopped - Short Packet */
|
||||
#define HCC_SPC(p) ((p) & (1 << 9))
|
||||
/* true: HC has Contiguous Frame ID Capability */
|
||||
#define HCC_CFC(p) ((p) & (1 << 11))
|
||||
/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */
|
||||
#define HCC_MAX_PSA(p) (1 << ((((p) >> 12) & 0xf) + 1))
|
||||
/* Extended Capabilities pointer from PCI base - section 5.3.6 */
|
||||
#define HCC_EXT_CAPS(p) XHCI_HCC_EXT_CAPS(p)
|
||||
|
||||
#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
|
||||
|
||||
/* db_off bitmask - bits 0:1 reserved */
|
||||
#define DBOFF_MASK (~0x3)
|
||||
|
||||
/* run_regs_off bitmask - bits 0:4 reserved */
|
||||
#define RTSOFF_MASK (~0x1f)
|
||||
|
||||
/* HCCPARAMS2 - hcc_params2 - bitmasks */
|
||||
/* true: HC supports U3 entry Capability */
|
||||
#define HCC2_U3C(p) ((p) & (1 << 0))
|
||||
/* true: HC supports Configure endpoint command Max exit latency too large */
|
||||
#define HCC2_CMC(p) ((p) & (1 << 1))
|
||||
/* true: HC supports Force Save context Capability */
|
||||
#define HCC2_FSC(p) ((p) & (1 << 2))
|
||||
/* true: HC supports Compliance Transition Capability */
|
||||
#define HCC2_CTC(p) ((p) & (1 << 3))
|
||||
/* true: HC support Large ESIT payload Capability > 48k */
|
||||
#define HCC2_LEC(p) ((p) & (1 << 4))
|
||||
/* true: HC support Configuration Information Capability */
|
||||
#define HCC2_CIC(p) ((p) & (1 << 5))
|
||||
/* true: HC support Extended TBC Capability, Isoc burst count > 65535 */
|
||||
#define HCC2_ETC(p) ((p) & (1 << 6))
|
||||
@@ -108,7 +108,7 @@ struct dbc_port {
|
||||
struct tasklet_struct push;
|
||||
|
||||
struct list_head write_pool;
|
||||
struct kfifo write_fifo;
|
||||
unsigned int tx_boundary;
|
||||
|
||||
bool registered;
|
||||
};
|
||||
|
||||
@@ -25,16 +25,26 @@ static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
dbc_send_packet(struct dbc_port *port, char *packet, unsigned int size)
|
||||
dbc_kfifo_to_req(struct dbc_port *port, char *packet)
|
||||
{
|
||||
unsigned int len;
|
||||
unsigned int len;
|
||||
|
||||
len = kfifo_len(&port->write_fifo);
|
||||
if (len < size)
|
||||
size = len;
|
||||
if (size != 0)
|
||||
size = kfifo_out(&port->write_fifo, packet, size);
|
||||
return size;
|
||||
len = kfifo_len(&port->port.xmit_fifo);
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
len = min(len, DBC_MAX_PACKET);
|
||||
|
||||
if (port->tx_boundary)
|
||||
len = min(port->tx_boundary, len);
|
||||
|
||||
len = kfifo_out(&port->port.xmit_fifo, packet, len);
|
||||
|
||||
if (port->tx_boundary)
|
||||
port->tx_boundary -= len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int dbc_start_tx(struct dbc_port *port)
|
||||
@@ -49,7 +59,7 @@ static int dbc_start_tx(struct dbc_port *port)
|
||||
|
||||
while (!list_empty(pool)) {
|
||||
req = list_entry(pool->next, struct dbc_request, list_pool);
|
||||
len = dbc_send_packet(port, req->buf, DBC_MAX_PACKET);
|
||||
len = dbc_kfifo_to_req(port, req->buf);
|
||||
if (len == 0)
|
||||
break;
|
||||
do_tty_wake = true;
|
||||
@@ -214,14 +224,32 @@ static int dbc_tty_write(struct tty_struct *tty,
|
||||
{
|
||||
struct dbc_port *port = tty->driver_data;
|
||||
unsigned long flags;
|
||||
unsigned int written = 0;
|
||||
|
||||
spin_lock_irqsave(&port->port_lock, flags);
|
||||
if (count)
|
||||
count = kfifo_in(&port->write_fifo, buf, count);
|
||||
dbc_start_tx(port);
|
||||
|
||||
/*
|
||||
* Treat tty write as one usb transfer. Make sure the writes are turned
|
||||
* into TRB request having the same size boundaries as the tty writes.
|
||||
* Don't add data to kfifo before previous write is turned into TRBs
|
||||
*/
|
||||
if (port->tx_boundary) {
|
||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
written = kfifo_in(&port->port.xmit_fifo, buf, count);
|
||||
|
||||
if (written == count)
|
||||
port->tx_boundary = kfifo_len(&port->port.xmit_fifo);
|
||||
|
||||
dbc_start_tx(port);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||
|
||||
return count;
|
||||
return written;
|
||||
}
|
||||
|
||||
static int dbc_tty_put_char(struct tty_struct *tty, unsigned char ch)
|
||||
@@ -231,7 +259,7 @@ static int dbc_tty_put_char(struct tty_struct *tty, unsigned char ch)
|
||||
int status;
|
||||
|
||||
spin_lock_irqsave(&port->port_lock, flags);
|
||||
status = kfifo_put(&port->write_fifo, ch);
|
||||
status = kfifo_put(&port->port.xmit_fifo, ch);
|
||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||
|
||||
return status;
|
||||
@@ -254,7 +282,11 @@ static unsigned int dbc_tty_write_room(struct tty_struct *tty)
|
||||
unsigned int room;
|
||||
|
||||
spin_lock_irqsave(&port->port_lock, flags);
|
||||
room = kfifo_avail(&port->write_fifo);
|
||||
room = kfifo_avail(&port->port.xmit_fifo);
|
||||
|
||||
if (port->tx_boundary)
|
||||
room = 0;
|
||||
|
||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||
|
||||
return room;
|
||||
@@ -267,7 +299,7 @@ static unsigned int dbc_tty_chars_in_buffer(struct tty_struct *tty)
|
||||
unsigned int chars;
|
||||
|
||||
spin_lock_irqsave(&port->port_lock, flags);
|
||||
chars = kfifo_len(&port->write_fifo);
|
||||
chars = kfifo_len(&port->port.xmit_fifo);
|
||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||
|
||||
return chars;
|
||||
@@ -425,7 +457,8 @@ static int xhci_dbc_tty_register_device(struct xhci_dbc *dbc)
|
||||
goto err_idr;
|
||||
}
|
||||
|
||||
ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL);
|
||||
ret = kfifo_alloc(&port->port.xmit_fifo, DBC_WRITE_BUF_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (ret)
|
||||
goto err_exit_port;
|
||||
|
||||
@@ -454,7 +487,7 @@ err_free_requests:
|
||||
xhci_dbc_free_requests(&port->read_pool);
|
||||
xhci_dbc_free_requests(&port->write_pool);
|
||||
err_free_fifo:
|
||||
kfifo_free(&port->write_fifo);
|
||||
kfifo_free(&port->port.xmit_fifo);
|
||||
err_exit_port:
|
||||
idr_remove(&dbc_tty_minors, port->minor);
|
||||
err_idr:
|
||||
@@ -479,7 +512,7 @@ static void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc)
|
||||
idr_remove(&dbc_tty_minors, port->minor);
|
||||
mutex_unlock(&dbc_tty_minors_lock);
|
||||
|
||||
kfifo_free(&port->write_fifo);
|
||||
kfifo_free(&port->port.xmit_fifo);
|
||||
xhci_dbc_free_requests(&port->read_pool);
|
||||
xhci_dbc_free_requests(&port->read_queue);
|
||||
xhci_dbc_free_requests(&port->write_pool);
|
||||
|
||||
176
drivers/usb/host/xhci-port.h
Normal file
176
drivers/usb/host/xhci-port.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
/* PORTSC - Port Status and Control Register - port_status_base bitmasks */
|
||||
/* true: device connected */
|
||||
#define PORT_CONNECT (1 << 0)
|
||||
/* true: port enabled */
|
||||
#define PORT_PE (1 << 1)
|
||||
/* bit 2 reserved and zeroed */
|
||||
/* true: port has an over-current condition */
|
||||
#define PORT_OC (1 << 3)
|
||||
/* true: port reset signaling asserted */
|
||||
#define PORT_RESET (1 << 4)
|
||||
/* Port Link State - bits 5:8
|
||||
* A read gives the current link PM state of the port,
|
||||
* a write with Link State Write Strobe set sets the link state.
|
||||
*/
|
||||
#define PORT_PLS_MASK (0xf << 5)
|
||||
#define XDEV_U0 (0x0 << 5)
|
||||
#define XDEV_U1 (0x1 << 5)
|
||||
#define XDEV_U2 (0x2 << 5)
|
||||
#define XDEV_U3 (0x3 << 5)
|
||||
#define XDEV_DISABLED (0x4 << 5)
|
||||
#define XDEV_RXDETECT (0x5 << 5)
|
||||
#define XDEV_INACTIVE (0x6 << 5)
|
||||
#define XDEV_POLLING (0x7 << 5)
|
||||
#define XDEV_RECOVERY (0x8 << 5)
|
||||
#define XDEV_HOT_RESET (0x9 << 5)
|
||||
#define XDEV_COMP_MODE (0xa << 5)
|
||||
#define XDEV_TEST_MODE (0xb << 5)
|
||||
#define XDEV_RESUME (0xf << 5)
|
||||
|
||||
/* true: port has power (see HCC_PPC) */
|
||||
#define PORT_POWER (1 << 9)
|
||||
/* bits 10:13 indicate device speed:
|
||||
* 0 - undefined speed - port hasn't be initialized by a reset yet
|
||||
* 1 - full speed
|
||||
* 2 - low speed
|
||||
* 3 - high speed
|
||||
* 4 - super speed
|
||||
* 5-15 reserved
|
||||
*/
|
||||
#define DEV_SPEED_MASK (0xf << 10)
|
||||
#define XDEV_FS (0x1 << 10)
|
||||
#define XDEV_LS (0x2 << 10)
|
||||
#define XDEV_HS (0x3 << 10)
|
||||
#define XDEV_SS (0x4 << 10)
|
||||
#define XDEV_SSP (0x5 << 10)
|
||||
#define DEV_UNDEFSPEED(p) (((p) & DEV_SPEED_MASK) == (0x0<<10))
|
||||
#define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_FS)
|
||||
#define DEV_LOWSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_LS)
|
||||
#define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_HS)
|
||||
#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS)
|
||||
#define DEV_SUPERSPEEDPLUS(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP)
|
||||
#define DEV_SUPERSPEED_ANY(p) (((p) & DEV_SPEED_MASK) >= XDEV_SS)
|
||||
#define DEV_PORT_SPEED(p) (((p) >> 10) & 0x0f)
|
||||
|
||||
/* Bits 20:23 in the Slot Context are the speed for the device */
|
||||
#define SLOT_SPEED_FS (XDEV_FS << 10)
|
||||
#define SLOT_SPEED_LS (XDEV_LS << 10)
|
||||
#define SLOT_SPEED_HS (XDEV_HS << 10)
|
||||
#define SLOT_SPEED_SS (XDEV_SS << 10)
|
||||
#define SLOT_SPEED_SSP (XDEV_SSP << 10)
|
||||
/* Port Indicator Control */
|
||||
#define PORT_LED_OFF (0 << 14)
|
||||
#define PORT_LED_AMBER (1 << 14)
|
||||
#define PORT_LED_GREEN (2 << 14)
|
||||
#define PORT_LED_MASK (3 << 14)
|
||||
/* Port Link State Write Strobe - set this when changing link state */
|
||||
#define PORT_LINK_STROBE (1 << 16)
|
||||
/* true: connect status change */
|
||||
#define PORT_CSC (1 << 17)
|
||||
/* true: port enable change */
|
||||
#define PORT_PEC (1 << 18)
|
||||
/* true: warm reset for a USB 3.0 device is done. A "hot" reset puts the port
|
||||
* into an enabled state, and the device into the default state. A "warm" reset
|
||||
* also resets the link, forcing the device through the link training sequence.
|
||||
* SW can also look at the Port Reset register to see when warm reset is done.
|
||||
*/
|
||||
#define PORT_WRC (1 << 19)
|
||||
/* true: over-current change */
|
||||
#define PORT_OCC (1 << 20)
|
||||
/* true: reset change - 1 to 0 transition of PORT_RESET */
|
||||
#define PORT_RC (1 << 21)
|
||||
/* port link status change - set on some port link state transitions:
|
||||
* Transition Reason
|
||||
* ------------------------------------------------------------------------------
|
||||
* - U3 to Resume Wakeup signaling from a device
|
||||
* - Resume to Recovery to U0 USB 3.0 device resume
|
||||
* - Resume to U0 USB 2.0 device resume
|
||||
* - U3 to Recovery to U0 Software resume of USB 3.0 device complete
|
||||
* - U3 to U0 Software resume of USB 2.0 device complete
|
||||
* - U2 to U0 L1 resume of USB 2.1 device complete
|
||||
* - U0 to U0 (???) L1 entry rejection by USB 2.1 device
|
||||
* - U0 to disabled L1 entry error with USB 2.1 device
|
||||
* - Any state to inactive Error on USB 3.0 port
|
||||
*/
|
||||
#define PORT_PLC (1 << 22)
|
||||
/* port configure error change - port failed to configure its link partner */
|
||||
#define PORT_CEC (1 << 23)
|
||||
#define PORT_CHANGE_MASK (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
|
||||
PORT_RC | PORT_PLC | PORT_CEC)
|
||||
|
||||
|
||||
/* Cold Attach Status - xHC can set this bit to report device attached during
|
||||
* Sx state. Warm port reset should be perfomed to clear this bit and move port
|
||||
* to connected state.
|
||||
*/
|
||||
#define PORT_CAS (1 << 24)
|
||||
/* wake on connect (enable) */
|
||||
#define PORT_WKCONN_E (1 << 25)
|
||||
/* wake on disconnect (enable) */
|
||||
#define PORT_WKDISC_E (1 << 26)
|
||||
/* wake on over-current (enable) */
|
||||
#define PORT_WKOC_E (1 << 27)
|
||||
/* bits 28:29 reserved */
|
||||
/* true: device is non-removable - for USB 3.0 roothub emulation */
|
||||
#define PORT_DEV_REMOVE (1 << 30)
|
||||
/* Initiate a warm port reset - complete when PORT_WRC is '1' */
|
||||
#define PORT_WR (1 << 31)
|
||||
|
||||
/* We mark duplicate entries with -1 */
|
||||
#define DUPLICATE_ENTRY ((u8)(-1))
|
||||
|
||||
/* Port Power Management Status and Control - port_power_base bitmasks */
|
||||
/* Inactivity timer value for transitions into U1, in microseconds.
|
||||
* Timeout can be up to 127us. 0xFF means an infinite timeout.
|
||||
*/
|
||||
#define PORT_U1_TIMEOUT(p) ((p) & 0xff)
|
||||
#define PORT_U1_TIMEOUT_MASK 0xff
|
||||
/* Inactivity timer value for transitions into U2 */
|
||||
#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8)
|
||||
#define PORT_U2_TIMEOUT_MASK (0xff << 8)
|
||||
/* Bits 24:31 for port testing */
|
||||
|
||||
/* USB2 Protocol PORTSPMSC */
|
||||
#define PORT_L1S_MASK 7
|
||||
#define PORT_L1S_SUCCESS 1
|
||||
#define PORT_RWE (1 << 3)
|
||||
#define PORT_HIRD(p) (((p) & 0xf) << 4)
|
||||
#define PORT_HIRD_MASK (0xf << 4)
|
||||
#define PORT_L1DS_MASK (0xff << 8)
|
||||
#define PORT_L1DS(p) (((p) & 0xff) << 8)
|
||||
#define PORT_HLE (1 << 16)
|
||||
#define PORT_TEST_MODE_SHIFT 28
|
||||
|
||||
/* USB3 Protocol PORTLI Port Link Information */
|
||||
#define PORT_RX_LANES(p) (((p) >> 16) & 0xf)
|
||||
#define PORT_TX_LANES(p) (((p) >> 20) & 0xf)
|
||||
|
||||
/* USB2 Protocol PORTHLPMC */
|
||||
#define PORT_HIRDM(p)((p) & 3)
|
||||
#define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2)
|
||||
#define PORT_BESLD(p)(((p) & 0xf) << 10)
|
||||
|
||||
/* use 512 microseconds as USB2 LPM L1 default timeout. */
|
||||
#define XHCI_L1_TIMEOUT 512
|
||||
|
||||
/* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency.
|
||||
* Safe to use with mixed HIRD and BESL systems (host and device) and is used
|
||||
* by other operating systems.
|
||||
*
|
||||
* XHCI 1.0 errata 8/14/12 Table 13 notes:
|
||||
* "Software should choose xHC BESL/BESLD field values that do not violate a
|
||||
* device's resume latency requirements,
|
||||
* e.g. not program values > '4' if BLC = '1' and a HIRD device is attached,
|
||||
* or not program values < '4' if BLC = '0' and a BESL device is attached.
|
||||
*/
|
||||
#define XHCI_DEFAULT_BESL 4
|
||||
|
||||
/*
|
||||
* USB3 specification define a 360ms tPollingLFPSTiemout for USB3 ports
|
||||
* to complete link training. usually link trainig completes much faster
|
||||
* so check status 10 times with 36ms sleep in places we need to wait for
|
||||
* polling to complete.
|
||||
*/
|
||||
#define XHCI_PORT_POLLING_LFPS_TIME 36
|
||||
@@ -23,6 +23,9 @@
|
||||
#include "xhci-ext-caps.h"
|
||||
#include "pci-quirks.h"
|
||||
|
||||
#include "xhci-port.h"
|
||||
#include "xhci-caps.h"
|
||||
|
||||
/* max buffer size for trace and debug messages */
|
||||
#define XHCI_MSG_MAX 500
|
||||
|
||||
@@ -63,90 +66,6 @@ struct xhci_cap_regs {
|
||||
/* Reserved up to (CAPLENGTH - 0x1C) */
|
||||
};
|
||||
|
||||
/* hc_capbase bitmasks */
|
||||
/* bits 7:0 - how long is the Capabilities register */
|
||||
#define HC_LENGTH(p) XHCI_HC_LENGTH(p)
|
||||
/* bits 31:16 */
|
||||
#define HC_VERSION(p) (((p) >> 16) & 0xffff)
|
||||
|
||||
/* HCSPARAMS1 - hcs_params1 - bitmasks */
|
||||
/* bits 0:7, Max Device Slots */
|
||||
#define HCS_MAX_SLOTS(p) (((p) >> 0) & 0xff)
|
||||
#define HCS_SLOTS_MASK 0xff
|
||||
/* bits 8:18, Max Interrupters */
|
||||
#define HCS_MAX_INTRS(p) (((p) >> 8) & 0x7ff)
|
||||
/* bits 24:31, Max Ports - max value is 0x7F = 127 ports */
|
||||
#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f)
|
||||
|
||||
/* HCSPARAMS2 - hcs_params2 - bitmasks */
|
||||
/* bits 0:3, frames or uframes that SW needs to queue transactions
|
||||
* ahead of the HW to meet periodic deadlines */
|
||||
#define HCS_IST(p) (((p) >> 0) & 0xf)
|
||||
/* bits 4:7, max number of Event Ring segments */
|
||||
#define HCS_ERST_MAX(p) (((p) >> 4) & 0xf)
|
||||
/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */
|
||||
/* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
|
||||
/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */
|
||||
#define HCS_MAX_SCRATCHPAD(p) ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f))
|
||||
|
||||
/* HCSPARAMS3 - hcs_params3 - bitmasks */
|
||||
/* bits 0:7, Max U1 to U0 latency for the roothub ports */
|
||||
#define HCS_U1_LATENCY(p) (((p) >> 0) & 0xff)
|
||||
/* bits 16:31, Max U2 to U0 latency for the roothub ports */
|
||||
#define HCS_U2_LATENCY(p) (((p) >> 16) & 0xffff)
|
||||
|
||||
/* HCCPARAMS - hcc_params - bitmasks */
|
||||
/* true: HC can use 64-bit address pointers */
|
||||
#define HCC_64BIT_ADDR(p) ((p) & (1 << 0))
|
||||
/* true: HC can do bandwidth negotiation */
|
||||
#define HCC_BANDWIDTH_NEG(p) ((p) & (1 << 1))
|
||||
/* true: HC uses 64-byte Device Context structures
|
||||
* FIXME 64-byte context structures aren't supported yet.
|
||||
*/
|
||||
#define HCC_64BYTE_CONTEXT(p) ((p) & (1 << 2))
|
||||
/* true: HC has port power switches */
|
||||
#define HCC_PPC(p) ((p) & (1 << 3))
|
||||
/* true: HC has port indicators */
|
||||
#define HCS_INDICATOR(p) ((p) & (1 << 4))
|
||||
/* true: HC has Light HC Reset Capability */
|
||||
#define HCC_LIGHT_RESET(p) ((p) & (1 << 5))
|
||||
/* true: HC supports latency tolerance messaging */
|
||||
#define HCC_LTC(p) ((p) & (1 << 6))
|
||||
/* true: no secondary Stream ID Support */
|
||||
#define HCC_NSS(p) ((p) & (1 << 7))
|
||||
/* true: HC supports Stopped - Short Packet */
|
||||
#define HCC_SPC(p) ((p) & (1 << 9))
|
||||
/* true: HC has Contiguous Frame ID Capability */
|
||||
#define HCC_CFC(p) ((p) & (1 << 11))
|
||||
/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */
|
||||
#define HCC_MAX_PSA(p) (1 << ((((p) >> 12) & 0xf) + 1))
|
||||
/* Extended Capabilities pointer from PCI base - section 5.3.6 */
|
||||
#define HCC_EXT_CAPS(p) XHCI_HCC_EXT_CAPS(p)
|
||||
|
||||
#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
|
||||
|
||||
/* db_off bitmask - bits 0:1 reserved */
|
||||
#define DBOFF_MASK (~0x3)
|
||||
|
||||
/* run_regs_off bitmask - bits 0:4 reserved */
|
||||
#define RTSOFF_MASK (~0x1f)
|
||||
|
||||
/* HCCPARAMS2 - hcc_params2 - bitmasks */
|
||||
/* true: HC supports U3 entry Capability */
|
||||
#define HCC2_U3C(p) ((p) & (1 << 0))
|
||||
/* true: HC supports Configure endpoint command Max exit latency too large */
|
||||
#define HCC2_CMC(p) ((p) & (1 << 1))
|
||||
/* true: HC supports Force Save context Capability */
|
||||
#define HCC2_FSC(p) ((p) & (1 << 2))
|
||||
/* true: HC supports Compliance Transition Capability */
|
||||
#define HCC2_CTC(p) ((p) & (1 << 3))
|
||||
/* true: HC support Large ESIT payload Capability > 48k */
|
||||
#define HCC2_LEC(p) ((p) & (1 << 4))
|
||||
/* true: HC support Configuration Information Capability */
|
||||
#define HCC2_CIC(p) ((p) & (1 << 5))
|
||||
/* true: HC support Extended TBC Capability, Isoc burst count > 65535 */
|
||||
#define HCC2_ETC(p) ((p) & (1 << 6))
|
||||
|
||||
/* Number of registers per port */
|
||||
#define NUM_PORT_REGS 4
|
||||
|
||||
@@ -292,181 +211,6 @@ struct xhci_op_regs {
|
||||
#define CONFIG_CIE (1 << 9)
|
||||
/* bits 10:31 - reserved and should be preserved */
|
||||
|
||||
/* PORTSC - Port Status and Control Register - port_status_base bitmasks */
|
||||
/* true: device connected */
|
||||
#define PORT_CONNECT (1 << 0)
|
||||
/* true: port enabled */
|
||||
#define PORT_PE (1 << 1)
|
||||
/* bit 2 reserved and zeroed */
|
||||
/* true: port has an over-current condition */
|
||||
#define PORT_OC (1 << 3)
|
||||
/* true: port reset signaling asserted */
|
||||
#define PORT_RESET (1 << 4)
|
||||
/* Port Link State - bits 5:8
|
||||
* A read gives the current link PM state of the port,
|
||||
* a write with Link State Write Strobe set sets the link state.
|
||||
*/
|
||||
#define PORT_PLS_MASK (0xf << 5)
|
||||
#define XDEV_U0 (0x0 << 5)
|
||||
#define XDEV_U1 (0x1 << 5)
|
||||
#define XDEV_U2 (0x2 << 5)
|
||||
#define XDEV_U3 (0x3 << 5)
|
||||
#define XDEV_DISABLED (0x4 << 5)
|
||||
#define XDEV_RXDETECT (0x5 << 5)
|
||||
#define XDEV_INACTIVE (0x6 << 5)
|
||||
#define XDEV_POLLING (0x7 << 5)
|
||||
#define XDEV_RECOVERY (0x8 << 5)
|
||||
#define XDEV_HOT_RESET (0x9 << 5)
|
||||
#define XDEV_COMP_MODE (0xa << 5)
|
||||
#define XDEV_TEST_MODE (0xb << 5)
|
||||
#define XDEV_RESUME (0xf << 5)
|
||||
|
||||
/* true: port has power (see HCC_PPC) */
|
||||
#define PORT_POWER (1 << 9)
|
||||
/* bits 10:13 indicate device speed:
|
||||
* 0 - undefined speed - port hasn't be initialized by a reset yet
|
||||
* 1 - full speed
|
||||
* 2 - low speed
|
||||
* 3 - high speed
|
||||
* 4 - super speed
|
||||
* 5-15 reserved
|
||||
*/
|
||||
#define DEV_SPEED_MASK (0xf << 10)
|
||||
#define XDEV_FS (0x1 << 10)
|
||||
#define XDEV_LS (0x2 << 10)
|
||||
#define XDEV_HS (0x3 << 10)
|
||||
#define XDEV_SS (0x4 << 10)
|
||||
#define XDEV_SSP (0x5 << 10)
|
||||
#define DEV_UNDEFSPEED(p) (((p) & DEV_SPEED_MASK) == (0x0<<10))
|
||||
#define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_FS)
|
||||
#define DEV_LOWSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_LS)
|
||||
#define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_HS)
|
||||
#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS)
|
||||
#define DEV_SUPERSPEEDPLUS(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP)
|
||||
#define DEV_SUPERSPEED_ANY(p) (((p) & DEV_SPEED_MASK) >= XDEV_SS)
|
||||
#define DEV_PORT_SPEED(p) (((p) >> 10) & 0x0f)
|
||||
|
||||
/* Bits 20:23 in the Slot Context are the speed for the device */
|
||||
#define SLOT_SPEED_FS (XDEV_FS << 10)
|
||||
#define SLOT_SPEED_LS (XDEV_LS << 10)
|
||||
#define SLOT_SPEED_HS (XDEV_HS << 10)
|
||||
#define SLOT_SPEED_SS (XDEV_SS << 10)
|
||||
#define SLOT_SPEED_SSP (XDEV_SSP << 10)
|
||||
/* Port Indicator Control */
|
||||
#define PORT_LED_OFF (0 << 14)
|
||||
#define PORT_LED_AMBER (1 << 14)
|
||||
#define PORT_LED_GREEN (2 << 14)
|
||||
#define PORT_LED_MASK (3 << 14)
|
||||
/* Port Link State Write Strobe - set this when changing link state */
|
||||
#define PORT_LINK_STROBE (1 << 16)
|
||||
/* true: connect status change */
|
||||
#define PORT_CSC (1 << 17)
|
||||
/* true: port enable change */
|
||||
#define PORT_PEC (1 << 18)
|
||||
/* true: warm reset for a USB 3.0 device is done. A "hot" reset puts the port
|
||||
* into an enabled state, and the device into the default state. A "warm" reset
|
||||
* also resets the link, forcing the device through the link training sequence.
|
||||
* SW can also look at the Port Reset register to see when warm reset is done.
|
||||
*/
|
||||
#define PORT_WRC (1 << 19)
|
||||
/* true: over-current change */
|
||||
#define PORT_OCC (1 << 20)
|
||||
/* true: reset change - 1 to 0 transition of PORT_RESET */
|
||||
#define PORT_RC (1 << 21)
|
||||
/* port link status change - set on some port link state transitions:
|
||||
* Transition Reason
|
||||
* ------------------------------------------------------------------------------
|
||||
* - U3 to Resume Wakeup signaling from a device
|
||||
* - Resume to Recovery to U0 USB 3.0 device resume
|
||||
* - Resume to U0 USB 2.0 device resume
|
||||
* - U3 to Recovery to U0 Software resume of USB 3.0 device complete
|
||||
* - U3 to U0 Software resume of USB 2.0 device complete
|
||||
* - U2 to U0 L1 resume of USB 2.1 device complete
|
||||
* - U0 to U0 (???) L1 entry rejection by USB 2.1 device
|
||||
* - U0 to disabled L1 entry error with USB 2.1 device
|
||||
* - Any state to inactive Error on USB 3.0 port
|
||||
*/
|
||||
#define PORT_PLC (1 << 22)
|
||||
/* port configure error change - port failed to configure its link partner */
|
||||
#define PORT_CEC (1 << 23)
|
||||
#define PORT_CHANGE_MASK (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
|
||||
PORT_RC | PORT_PLC | PORT_CEC)
|
||||
|
||||
|
||||
/* Cold Attach Status - xHC can set this bit to report device attached during
|
||||
* Sx state. Warm port reset should be perfomed to clear this bit and move port
|
||||
* to connected state.
|
||||
*/
|
||||
#define PORT_CAS (1 << 24)
|
||||
/* wake on connect (enable) */
|
||||
#define PORT_WKCONN_E (1 << 25)
|
||||
/* wake on disconnect (enable) */
|
||||
#define PORT_WKDISC_E (1 << 26)
|
||||
/* wake on over-current (enable) */
|
||||
#define PORT_WKOC_E (1 << 27)
|
||||
/* bits 28:29 reserved */
|
||||
/* true: device is non-removable - for USB 3.0 roothub emulation */
|
||||
#define PORT_DEV_REMOVE (1 << 30)
|
||||
/* Initiate a warm port reset - complete when PORT_WRC is '1' */
|
||||
#define PORT_WR (1 << 31)
|
||||
|
||||
/* We mark duplicate entries with -1 */
|
||||
#define DUPLICATE_ENTRY ((u8)(-1))
|
||||
|
||||
/* Port Power Management Status and Control - port_power_base bitmasks */
|
||||
/* Inactivity timer value for transitions into U1, in microseconds.
|
||||
* Timeout can be up to 127us. 0xFF means an infinite timeout.
|
||||
*/
|
||||
#define PORT_U1_TIMEOUT(p) ((p) & 0xff)
|
||||
#define PORT_U1_TIMEOUT_MASK 0xff
|
||||
/* Inactivity timer value for transitions into U2 */
|
||||
#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8)
|
||||
#define PORT_U2_TIMEOUT_MASK (0xff << 8)
|
||||
/* Bits 24:31 for port testing */
|
||||
|
||||
/* USB2 Protocol PORTSPMSC */
|
||||
#define PORT_L1S_MASK 7
|
||||
#define PORT_L1S_SUCCESS 1
|
||||
#define PORT_RWE (1 << 3)
|
||||
#define PORT_HIRD(p) (((p) & 0xf) << 4)
|
||||
#define PORT_HIRD_MASK (0xf << 4)
|
||||
#define PORT_L1DS_MASK (0xff << 8)
|
||||
#define PORT_L1DS(p) (((p) & 0xff) << 8)
|
||||
#define PORT_HLE (1 << 16)
|
||||
#define PORT_TEST_MODE_SHIFT 28
|
||||
|
||||
/* USB3 Protocol PORTLI Port Link Information */
|
||||
#define PORT_RX_LANES(p) (((p) >> 16) & 0xf)
|
||||
#define PORT_TX_LANES(p) (((p) >> 20) & 0xf)
|
||||
|
||||
/* USB2 Protocol PORTHLPMC */
|
||||
#define PORT_HIRDM(p)((p) & 3)
|
||||
#define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2)
|
||||
#define PORT_BESLD(p)(((p) & 0xf) << 10)
|
||||
|
||||
/* use 512 microseconds as USB2 LPM L1 default timeout. */
|
||||
#define XHCI_L1_TIMEOUT 512
|
||||
|
||||
/* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency.
|
||||
* Safe to use with mixed HIRD and BESL systems (host and device) and is used
|
||||
* by other operating systems.
|
||||
*
|
||||
* XHCI 1.0 errata 8/14/12 Table 13 notes:
|
||||
* "Software should choose xHC BESL/BESLD field values that do not violate a
|
||||
* device's resume latency requirements,
|
||||
* e.g. not program values > '4' if BLC = '1' and a HIRD device is attached,
|
||||
* or not program values < '4' if BLC = '0' and a BESL device is attached.
|
||||
*/
|
||||
#define XHCI_DEFAULT_BESL 4
|
||||
|
||||
/*
|
||||
* USB3 specification define a 360ms tPollingLFPSTiemout for USB3 ports
|
||||
* to complete link training. usually link trainig completes much faster
|
||||
* so check status 10 times with 36ms sleep in places we need to wait for
|
||||
* polling to complete.
|
||||
*/
|
||||
#define XHCI_PORT_POLLING_LFPS_TIME 36
|
||||
|
||||
/**
|
||||
* struct xhci_intr_reg - Interrupt Register Set
|
||||
* @irq_pending: IMAN - Interrupt Management Register. Used to enable
|
||||
|
||||
@@ -503,6 +503,7 @@ static void typec_altmode_release(struct device *dev)
|
||||
typec_altmode_put_partner(alt);
|
||||
|
||||
altmode_id_remove(alt->adev.dev.parent, alt->id);
|
||||
put_device(alt->adev.dev.parent);
|
||||
kfree(alt);
|
||||
}
|
||||
|
||||
@@ -552,6 +553,8 @@ typec_register_altmode(struct device *parent,
|
||||
alt->adev.dev.type = &typec_altmode_dev_type;
|
||||
dev_set_name(&alt->adev.dev, "%s.%u", dev_name(parent), id);
|
||||
|
||||
get_device(alt->adev.dev.parent);
|
||||
|
||||
/* Link partners and plugs with the ports */
|
||||
if (!is_port)
|
||||
typec_altmode_set_partner(alt);
|
||||
|
||||
@@ -3562,6 +3562,8 @@ void btrfs_free_reserved_bytes(struct btrfs_block_group *cache,
|
||||
spin_lock(&cache->lock);
|
||||
if (cache->ro)
|
||||
space_info->bytes_readonly += num_bytes;
|
||||
else if (btrfs_is_zoned(cache->fs_info))
|
||||
space_info->bytes_zone_unusable += num_bytes;
|
||||
cache->reserved -= num_bytes;
|
||||
space_info->bytes_reserved -= num_bytes;
|
||||
space_info->max_extent_size = 0;
|
||||
|
||||
@@ -341,8 +341,8 @@ btrfs_search_dir_index_item(struct btrfs_root *root, struct btrfs_path *path,
|
||||
return di;
|
||||
}
|
||||
/* Adjust return code if the key was not found in the next leaf. */
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
if (ret >= 0)
|
||||
ret = -ENOENT;
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
@@ -4532,11 +4532,8 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
|
||||
*/
|
||||
if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) {
|
||||
di = btrfs_search_dir_index_item(root, path, dir_ino, &fname.disk_name);
|
||||
if (IS_ERR_OR_NULL(di)) {
|
||||
if (!di)
|
||||
ret = -ENOENT;
|
||||
else
|
||||
ret = PTR_ERR(di);
|
||||
if (IS_ERR(di)) {
|
||||
ret = PTR_ERR(di);
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
21
fs/exec.c
21
fs/exec.c
@@ -142,13 +142,11 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* may_open() has already checked for this, so it should be
|
||||
* impossible to trip now. But we need to be extra cautious
|
||||
* and check again at the very end too.
|
||||
* Check do_open_execat() for an explanation.
|
||||
*/
|
||||
error = -EACCES;
|
||||
if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) ||
|
||||
path_noexec(&file->f_path)))
|
||||
if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
|
||||
path_noexec(&file->f_path))
|
||||
goto exit;
|
||||
|
||||
fsnotify_open(file);
|
||||
@@ -928,16 +926,16 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
|
||||
|
||||
file = do_filp_open(fd, name, &open_exec_flags);
|
||||
if (IS_ERR(file))
|
||||
goto out;
|
||||
return file;
|
||||
|
||||
/*
|
||||
* may_open() has already checked for this, so it should be
|
||||
* impossible to trip now. But we need to be extra cautious
|
||||
* and check again at the very end too.
|
||||
* In the past the regular type check was here. It moved to may_open() in
|
||||
* 633fb6ac3980 ("exec: move S_ISREG() check earlier"). Since then it is
|
||||
* an invariant that all non-regular files error out before we get here.
|
||||
*/
|
||||
err = -EACCES;
|
||||
if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) ||
|
||||
path_noexec(&file->f_path)))
|
||||
if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
|
||||
path_noexec(&file->f_path))
|
||||
goto exit;
|
||||
|
||||
err = deny_write_access(file);
|
||||
@@ -947,7 +945,6 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
|
||||
if (name->name[0] != '\0')
|
||||
fsnotify_open(file);
|
||||
|
||||
out:
|
||||
return file;
|
||||
|
||||
exit:
|
||||
|
||||
@@ -187,7 +187,7 @@ int dbMount(struct inode *ipbmap)
|
||||
}
|
||||
|
||||
bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag);
|
||||
if (!bmp->db_numag || bmp->db_numag >= MAXAG) {
|
||||
if (!bmp->db_numag || bmp->db_numag > MAXAG) {
|
||||
err = -EINVAL;
|
||||
goto err_release_metapage;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,8 @@ void nilfs_forget_buffer(struct buffer_head *bh)
|
||||
const unsigned long clear_bits =
|
||||
(BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
|
||||
BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
|
||||
BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected));
|
||||
BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected) |
|
||||
BIT(BH_Delay));
|
||||
|
||||
lock_buffer(bh);
|
||||
set_mask_bits(&bh->b_state, clear_bits, 0);
|
||||
@@ -409,7 +410,8 @@ void nilfs_clear_dirty_page(struct page *page, bool silent)
|
||||
const unsigned long clear_bits =
|
||||
(BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
|
||||
BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
|
||||
BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected));
|
||||
BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected) |
|
||||
BIT(BH_Delay));
|
||||
|
||||
bh = head = page_buffers(page);
|
||||
do {
|
||||
|
||||
@@ -193,8 +193,9 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
{
|
||||
const struct MFT_REC *rec = mi->mrec;
|
||||
u32 used = le32_to_cpu(rec->used);
|
||||
u32 t32, off, asize;
|
||||
u32 t32, off, asize, prev_type;
|
||||
u16 t16;
|
||||
u64 data_size, alloc_size, tot_size;
|
||||
|
||||
if (!attr) {
|
||||
u32 total = le32_to_cpu(rec->total);
|
||||
@@ -213,6 +214,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
if (!is_rec_inuse(rec))
|
||||
return NULL;
|
||||
|
||||
prev_type = 0;
|
||||
attr = Add2Ptr(rec, off);
|
||||
} else {
|
||||
/* Check if input attr inside record. */
|
||||
@@ -226,6 +228,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Overflow check. */
|
||||
if (off + asize < off)
|
||||
return NULL;
|
||||
|
||||
prev_type = le32_to_cpu(attr->type);
|
||||
attr = Add2Ptr(attr, asize);
|
||||
off += asize;
|
||||
}
|
||||
@@ -245,7 +252,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
|
||||
/* 0x100 is last known attribute for now. */
|
||||
t32 = le32_to_cpu(attr->type);
|
||||
if ((t32 & 0xf) || (t32 > 0x100))
|
||||
if (!t32 || (t32 & 0xf) || (t32 > 0x100))
|
||||
return NULL;
|
||||
|
||||
/* attributes in record must be ordered by type */
|
||||
if (t32 < prev_type)
|
||||
return NULL;
|
||||
|
||||
/* Check overflow and boundary. */
|
||||
@@ -254,16 +265,15 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
|
||||
/* Check size of attribute. */
|
||||
if (!attr->non_res) {
|
||||
/* Check resident fields. */
|
||||
if (asize < SIZEOF_RESIDENT)
|
||||
return NULL;
|
||||
|
||||
t16 = le16_to_cpu(attr->res.data_off);
|
||||
|
||||
if (t16 > asize)
|
||||
return NULL;
|
||||
|
||||
t32 = le32_to_cpu(attr->res.data_size);
|
||||
if (t16 + t32 > asize)
|
||||
if (t16 + le32_to_cpu(attr->res.data_size) > asize)
|
||||
return NULL;
|
||||
|
||||
if (attr->name_len &&
|
||||
@@ -274,21 +284,52 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
return attr;
|
||||
}
|
||||
|
||||
/* Check some nonresident fields. */
|
||||
if (attr->name_len &&
|
||||
le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
|
||||
le16_to_cpu(attr->nres.run_off)) {
|
||||
/* Check nonresident fields. */
|
||||
if (attr->non_res != 1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (attr->nres.svcn || !is_attr_ext(attr)) {
|
||||
t16 = le16_to_cpu(attr->nres.run_off);
|
||||
if (t16 > asize)
|
||||
return NULL;
|
||||
|
||||
t32 = sizeof(short) * attr->name_len;
|
||||
if (t32 && le16_to_cpu(attr->name_off) + t32 > t16)
|
||||
return NULL;
|
||||
|
||||
/* Check start/end vcn. */
|
||||
if (le64_to_cpu(attr->nres.svcn) > le64_to_cpu(attr->nres.evcn) + 1)
|
||||
return NULL;
|
||||
|
||||
data_size = le64_to_cpu(attr->nres.data_size);
|
||||
if (le64_to_cpu(attr->nres.valid_size) > data_size)
|
||||
return NULL;
|
||||
|
||||
alloc_size = le64_to_cpu(attr->nres.alloc_size);
|
||||
if (data_size > alloc_size)
|
||||
return NULL;
|
||||
|
||||
t32 = mi->sbi->cluster_mask;
|
||||
if (alloc_size & t32)
|
||||
return NULL;
|
||||
|
||||
if (!attr->nres.svcn && is_attr_ext(attr)) {
|
||||
/* First segment of sparse/compressed attribute */
|
||||
if (asize + 8 < SIZEOF_NONRESIDENT_EX)
|
||||
return NULL;
|
||||
|
||||
tot_size = le64_to_cpu(attr->nres.total_size);
|
||||
if (tot_size & t32)
|
||||
return NULL;
|
||||
|
||||
if (tot_size > alloc_size)
|
||||
return NULL;
|
||||
} else {
|
||||
if (asize + 8 < SIZEOF_NONRESIDENT)
|
||||
return NULL;
|
||||
|
||||
if (attr->nres.c_unit)
|
||||
return NULL;
|
||||
} else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
@@ -1384,6 +1384,8 @@ SYSCALL_DEFINE4(openat2, int, dfd, const char __user *, filename,
|
||||
|
||||
if (unlikely(usize < OPEN_HOW_SIZE_VER0))
|
||||
return -EINVAL;
|
||||
if (unlikely(usize > PAGE_SIZE))
|
||||
return -E2BIG;
|
||||
|
||||
err = copy_struct_from_user(&tmp, sizeof(tmp), how, usize);
|
||||
if (err)
|
||||
|
||||
@@ -3131,6 +3131,15 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
|
||||
return rc;
|
||||
|
||||
if (indatalen) {
|
||||
unsigned int len;
|
||||
|
||||
if (WARN_ON_ONCE(smb3_encryption_required(tcon) &&
|
||||
(check_add_overflow(total_len - 1,
|
||||
ALIGN(indatalen, 8), &len) ||
|
||||
len > MAX_CIFS_SMALL_BUFFER_SIZE))) {
|
||||
cifs_small_buf_release(req);
|
||||
return -EIO;
|
||||
}
|
||||
/*
|
||||
* indatalen is usually small at a couple of bytes max, so
|
||||
* just allocate through generic pool
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user