Merge 1b1391b9c4 ("Merge tag 'block-6.18-20251009' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux") into android-mainline

Steps on the way to v6.18-rc1

Change-Id: I0878507bc2b5daff8aae875d48cf518050fa1cf1
Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
Carlos Llamas authored and Treehugger Robot committed 2025-11-05 19:16:40 -08:00
commit 3b55e4052d
91 files changed
+1314 -733

No files matched your search

@@ -0,0 +1,51 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/hisilicon,hix5hd2-i2c.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: I2C for HiSilicon hix5hd2 chipset platform
maintainers:
- Wei Yan <sledge.yanwei@huawei.com>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
enum:
- hisilicon,hix5hd2-i2c
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
clock-frequency:
description: Desired I2C bus frequency in Hz
default: 100000
required:
- compatible
- reg
- interrupts
- clocks
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/hix5hd2-clock.h>
i2c@f8b10000 {
compatible = "hisilicon,hix5hd2-i2c";
reg = <0xf8b10000 0x1000>;
interrupts = <0 38 4>;
clocks = <&clock HIX5HD2_I2C0_RST>;
#address-cells = <1>;
#size-cells = <0>;
};
@@ -1,24 +0,0 @@
I2C for Hisilicon hix5hd2 chipset platform
Required properties:
- compatible: Must be "hisilicon,hix5hd2-i2c"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: interrupt number to the cpu.
- #address-cells = <1>;
- #size-cells = <0>;
- clocks: phandles to input clocks.
Optional properties:
- clock-frequency: Desired I2C bus frequency in Hz, otherwise defaults to 100000
- Child nodes conforming to i2c bus binding
Examples:
I2C0@f8b10000 {
compatible = "hisilicon,hix5hd2-i2c";
reg = <0xf8b10000 0x1000>;
interrupts = <0 38 4>;
clocks = <&clock HIX5HD2_I2C0_RST>;
#address-cells = <1>;
#size-cells = <0>;
}
@@ -10,9 +10,11 @@ maintainers:
- Chris Packham <chris.packham@alliedtelesis.co.nz>
description:
The RTL9300 SoC has two I2C controllers. Each of these has an SCL line (which
RTL9300 SoCs have two I2C controllers. Each of these has an SCL line (which
if not-used for SCL can be a GPIO). There are 8 common SDA lines that can be
assigned to either I2C controller.
RTL9310 SoCs have equal capabilities but support 12 common SDA lines which
can be assigned to either I2C controller.
properties:
compatible:
@@ -23,11 +25,19 @@ properties:
- realtek,rtl9302c-i2c
- realtek,rtl9303-i2c
- const: realtek,rtl9301-i2c
- const: realtek,rtl9301-i2c
- items:
- enum:
- realtek,rtl9311-i2c
- realtek,rtl9312-i2c
- realtek,rtl9313-i2c
- const: realtek,rtl9310-i2c
- enum:
- realtek,rtl9301-i2c
- realtek,rtl9310-i2c
reg:
items:
- description: Register offset and size this I2C controller.
- description: Register offset and size of this I2C controller.
"#address-cells":
const: 1
@@ -35,19 +45,44 @@ properties:
"#size-cells":
const: 0
realtek,scl:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The SCL line number of this I2C controller.
enum: [ 0, 1 ]
patternProperties:
'^i2c@[0-7]$':
'^i2c@[0-9ab]$':
$ref: /schemas/i2c/i2c-controller.yaml
unevaluatedProperties: false
properties:
reg:
description: The SDA pin associated with the I2C bus.
description: The SDA line number associated with the I2C bus.
maxItems: 1
required:
- reg
allOf:
- if:
properties:
compatible:
contains:
const: realtek,rtl9310-i2c
then:
required:
- realtek,scl
- if:
properties:
compatible:
contains:
const: realtek,rtl9301-i2c
then:
patternProperties:
'^i2c@[89ab]$': false
required:
- compatible
- reg
+3 -5
View File
@@ -1,8 +1,6 @@
=================
What is aty128fb?
=================
.. [This file is cloned from VesaFB/matroxfb]
=========================================
aty128fb - ATI Rage128 framebuffer driver
=========================================
This is a driver for a graphic framebuffer for ATI Rage128 based devices
on Intel and PPC boxes.
+3 -3
View File
@@ -1,6 +1,6 @@
==============
What is efifb?
==============
===================================
efifb - Generic EFI platform driver
===================================
This is a generic EFI platform driver for systems with UEFI firmware. The
system must be booted via the EFI stub for this to be usable. efifb supports
-4
View File
@@ -41,7 +41,6 @@ your board initialisation function::
ep93xx_register_fb(&some_board_fb_info);
=====================
Video Attribute Flags
=====================
@@ -79,7 +78,6 @@ EP93XXFB_USE_SDCSN2 Use SDCSn[2] for the framebuffer.
EP93XXFB_USE_SDCSN3 Use SDCSn[3] for the framebuffer.
=============================== ======================================
==================
Platform callbacks
==================
@@ -101,7 +99,6 @@ obtained as follows::
/* Board specific framebuffer setup */
}
======================
Setting the video mode
======================
@@ -119,7 +116,6 @@ set when the module is installed::
modprobe ep93xx-fb video=320x240
==============
Screenpage bug
==============
+3 -5
View File
@@ -1,8 +1,6 @@
=============
What is gxfb?
=============
.. [This file is cloned from VesaFB/aty128fb]
=======================================
gxfb - AMD Geode GX2 framebuffer driver
=======================================
This is a graphics framebuffer driver for AMD Geode GX2 based processors.
+45 -35
View File
@@ -4,42 +4,52 @@
Frame Buffer
============
.. toctree::
:maxdepth: 1
General information
===================
api
arkfb
aty128fb
cirrusfb
cmap_xfbdev
deferred_io
efifb
ep93xx-fb
fbcon
framebuffer
gxfb
intel810
internals
lxfb
matroxfb
metronomefb
modedb
pvr2fb
pxafb
s3fb
sa1100fb
sh7760fb
sisfb
sm501
sm712fb
sstfb
tgafb
tridentfb
udlfb
uvesafb
vesafb
viafb
vt8623fb
.. toctree::
:maxdepth: 1
api
cmap_xfbdev
deferred_io
fbcon
framebuffer
internals
modedb
Driver documentation
====================
.. toctree::
:maxdepth: 1
arkfb
aty128fb
cirrusfb
efifb
ep93xx-fb
gxfb
intel810
lxfb
matroxfb
metronomefb
pvr2fb
pxafb
s3fb
sa1100fb
sh7760fb
sisfb
sm501
sm712fb
sstfb
tgafb
tridentfb
udlfb
uvesafb
vesafb
viafb
vt8623fb
.. only:: subproject and html
+3 -6
View File
@@ -1,9 +1,6 @@
=============
What is lxfb?
=============
.. [This file is cloned from VesaFB/aty128fb]
======================================
lxfb - AMD Geode LX framebuffer driver
======================================
This is a graphics framebuffer driver for AMD Geode LX based processors.
+3 -6
View File
@@ -1,9 +1,6 @@
=================
What is matroxfb?
=================
.. [This file is cloned from VesaFB. Thanks go to Gerd Knorr]
================================================
matroxfb - Framebuffer driver for Matrox devices
================================================
This is a driver for a graphic framebuffer for Matrox devices on
Alpha, Intel and PPC boxes.
+3 -3
View File
@@ -1,6 +1,6 @@
===============
What is pvr2fb?
===============
===============================================
pvr2fb - PowerVR 2 graphics frame buffer driver
===============================================
This is a driver for PowerVR 2 based graphics frame buffers, such as the
one found in the Dreamcast.
+3 -6
View File
@@ -1,9 +1,6 @@
=================
What is sa1100fb?
=================
.. [This file is cloned from VesaFB/matroxfb]
=================================================
sa1100fb - SA-1100 LCD graphic framebuffer driver
=================================================
This is a driver for a graphic framebuffer for the SA-1100 LCD
controller.
+3 -3
View File
@@ -1,6 +1,6 @@
==============
What is sisfb?
==============
=====================================
sisfb - SiS framebuffer device driver
=====================================
sisfb is a framebuffer device driver for SiS (Silicon Integrated Systems)
graphics chips. Supported are:
+3 -3
View File
@@ -1,6 +1,6 @@
================
What is sm712fb?
================
==========================================================
sm712fb - Silicon Motion SM712 graphics framebuffer driver
==========================================================
This is a graphics framebuffer driver for Silicon Motion SM712 based processors.
+3 -3
View File
@@ -1,6 +1,6 @@
==============
What is tgafb?
==============
=======================================
tgafb - TGA graphics framebuffer driver
=======================================
This is a driver for DECChip 21030 based graphics framebuffers, a.k.a. TGA
cards, which are usually found in older Digital Alpha systems. The
+3 -3
View File
@@ -1,6 +1,6 @@
==============
What is udlfb?
==============
==================================
udlfb - DisplayLink USB 2.0 driver
==================================
This is a driver for DisplayLink USB 2.0 era graphics chips.
+3 -3
View File
@@ -1,6 +1,6 @@
===============
What is vesafb?
===============
===========================================
vesafb - Generic graphic framebuffer driver
===========================================
This is a generic driver for a graphic framebuffer on intel boxes.
+1 -1
View File
@@ -66,7 +66,7 @@ FX-bus
name='Clock Source',index=0
---------------------------
This control allows switching the word clock between interally generated
This control allows switching the word clock between internally generated
44.1 or 48 kHz, or a number of external sources.
Note: the sources for the 1616 CardBus card are unclear. Please report your
+1
View File
@@ -18345,6 +18345,7 @@ F: Documentation/core-api/symbol-namespaces.rst
F: scripts/nsdeps
NTB AMD DRIVER
M: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
L: ntb@lists.linux.dev
S: Supported
+3
View File
@@ -31,6 +31,9 @@ config PARISC
select HAVE_KERNEL_UNCOMPRESSED
select HAVE_PCI
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select PERF_USE_VMALLOC
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZ4
+7 -1
View File
@@ -1,6 +1,12 @@
#ifndef __ASM_PARISC_PERF_EVENT_H
#define __ASM_PARISC_PERF_EVENT_H
/* Empty, just to avoid compiling error */
#include <asm/psw.h>
#define perf_arch_fetch_caller_regs(regs, __ip) { \
(regs)->gr[0] = KERNEL_PSW; \
(regs)->iaoq[0] = (__ip); \
asm volatile("copy %%sp, %0\n":"=r"((regs)->gr[30])); \
}
#endif /* __ASM_PARISC_PERF_EVENT_H */
+4 -4
View File
@@ -10,10 +10,10 @@
#define TCSETS _IOW('T', 17, struct termios) /* TCSETATTR */
#define TCSETSW _IOW('T', 18, struct termios) /* TCSETATTRD */
#define TCSETSF _IOW('T', 19, struct termios) /* TCSETATTRF */
#define TCGETA _IOR('T', 1, struct termio)
#define TCSETA _IOW('T', 2, struct termio)
#define TCSETAW _IOW('T', 3, struct termio)
#define TCSETAF _IOW('T', 4, struct termio)
#define TCGETA 0x40125401
#define TCSETA 0x80125402
#define TCSETAW 0x80125403
#define TCSETAF 0x80125404
#define TCSBRK _IO('T', 5)
#define TCXONC _IO('T', 6)
#define TCFLSH _IO('T', 7)
+63
View File
@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_ASM_PARISC_PERF_REGS_H
#define _UAPI_ASM_PARISC_PERF_REGS_H
/* see struct user_regs_struct */
enum perf_event_parisc_regs {
PERF_REG_PARISC_R0, /* PSW is in gr[0] */
PERF_REG_PARISC_R1,
PERF_REG_PARISC_R2,
PERF_REG_PARISC_R3,
PERF_REG_PARISC_R4,
PERF_REG_PARISC_R5,
PERF_REG_PARISC_R6,
PERF_REG_PARISC_R7,
PERF_REG_PARISC_R8,
PERF_REG_PARISC_R9,
PERF_REG_PARISC_R10,
PERF_REG_PARISC_R11,
PERF_REG_PARISC_R12,
PERF_REG_PARISC_R13,
PERF_REG_PARISC_R14,
PERF_REG_PARISC_R15,
PERF_REG_PARISC_R16,
PERF_REG_PARISC_R17,
PERF_REG_PARISC_R18,
PERF_REG_PARISC_R19,
PERF_REG_PARISC_R20,
PERF_REG_PARISC_R21,
PERF_REG_PARISC_R22,
PERF_REG_PARISC_R23,
PERF_REG_PARISC_R24,
PERF_REG_PARISC_R25,
PERF_REG_PARISC_R26,
PERF_REG_PARISC_R27,
PERF_REG_PARISC_R28,
PERF_REG_PARISC_R29,
PERF_REG_PARISC_R30,
PERF_REG_PARISC_R31,
PERF_REG_PARISC_SR0,
PERF_REG_PARISC_SR1,
PERF_REG_PARISC_SR2,
PERF_REG_PARISC_SR3,
PERF_REG_PARISC_SR4,
PERF_REG_PARISC_SR5,
PERF_REG_PARISC_SR6,
PERF_REG_PARISC_SR7,
PERF_REG_PARISC_IAOQ0,
PERF_REG_PARISC_IAOQ1,
PERF_REG_PARISC_IASQ0,
PERF_REG_PARISC_IASQ1,
PERF_REG_PARISC_SAR, /* CR11 */
PERF_REG_PARISC_IIR, /* CR19 */
PERF_REG_PARISC_ISR, /* CR20 */
PERF_REG_PARISC_IOR, /* CR21 */
PERF_REG_PARISC_IPSW, /* CR22 */
PERF_REG_PARISC_MAX
};
#endif /* _UAPI_ASM_PARISC_PERF_REGS_H */
+1
View File
@@ -38,6 +38,7 @@ obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += topology.o
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_regs.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_KEXEC_CORE) += kexec.o relocate_kernel.o
+6
View File
@@ -995,6 +995,7 @@ static __init int qemu_print_iodc_data(struct device *lin_dev, void *data)
struct pdc_system_map_mod_info pdc_mod_info;
struct pdc_module_path mod_path;
memset(&iodc_data, 0, sizeof(iodc_data));
status = pdc_iodc_read(&count, hpa, 0,
&iodc_data, sizeof(iodc_data));
if (status != PDC_OK) {
@@ -1012,6 +1013,11 @@ static __init int qemu_print_iodc_data(struct device *lin_dev, void *data)
mod_index = 0;
do {
/* initialize device path for old machines */
memset(&mod_path, 0xff, sizeof(mod_path));
get_node_path(dev->dev.parent, &mod_path.path);
mod_path.path.mod = dev->hw_path;
memset(&pdc_mod_info, 0, sizeof(pdc_mod_info));
status = pdc_system_map_find_mods(&pdc_mod_info,
&mod_path, mod_index++);
} while (status == PDC_OK && pdc_mod_info.mod_addr != hpa);
+2 -1
View File
@@ -464,7 +464,8 @@ int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
unsigned long flags;
spin_lock_irqsave(&pdc_lock, flags);
retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
memcpy(pdc_result2, mod_path, sizeof(*mod_path));
retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
__pa(pdc_result2), mod_index);
convert_to_wide(pdc_result);
memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info));
+27
View File
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Performance event support for parisc
*
* Copyright (C) 2025 by Helge Deller <deller@gmx.de>
*/
#include <linux/kernel.h>
#include <linux/perf_event.h>
#include <asm/unwind.h>
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
{
struct unwind_frame_info info;
unwind_frame_init_task(&info, current, NULL);
while (1) {
if (unwind_once(&info) < 0 || info.ip == 0)
break;
if (!__kernel_text_address(info.ip) ||
perf_callchain_store(entry, info.ip))
return;
}
}
+61
View File
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2025 by Helge Deller <deller@gmx.de> */
#include <linux/perf_event.h>
#include <linux/perf_regs.h>
#include <asm/ptrace.h>
u64 perf_reg_value(struct pt_regs *regs, int idx)
{
switch (idx) {
case PERF_REG_PARISC_R0 ... PERF_REG_PARISC_R31:
return regs->gr[idx - PERF_REG_PARISC_R0];
case PERF_REG_PARISC_SR0 ... PERF_REG_PARISC_SR7:
return regs->sr[idx - PERF_REG_PARISC_SR0];
case PERF_REG_PARISC_IASQ0 ... PERF_REG_PARISC_IASQ1:
return regs->iasq[idx - PERF_REG_PARISC_IASQ0];
case PERF_REG_PARISC_IAOQ0 ... PERF_REG_PARISC_IAOQ1:
return regs->iasq[idx - PERF_REG_PARISC_IAOQ0];
case PERF_REG_PARISC_SAR: /* CR11 */
return regs->sar;
case PERF_REG_PARISC_IIR: /* CR19 */
return regs->iir;
case PERF_REG_PARISC_ISR: /* CR20 */
return regs->isr;
case PERF_REG_PARISC_IOR: /* CR21 */
return regs->ior;
case PERF_REG_PARISC_IPSW: /* CR22 */
return regs->ipsw;
};
WARN_ON_ONCE((u32)idx >= PERF_REG_PARISC_MAX);
return 0;
}
#define REG_RESERVED (~((1ULL << PERF_REG_PARISC_MAX) - 1))
int perf_reg_validate(u64 mask)
{
if (!mask || mask & REG_RESERVED)
return -EINVAL;
return 0;
}
u64 perf_reg_abi(struct task_struct *task)
{
if (!IS_ENABLED(CONFIG_64BIT))
return PERF_SAMPLE_REGS_ABI_32;
if (test_tsk_thread_flag(task, TIF_32BIT))
return PERF_SAMPLE_REGS_ABI_32;
return PERF_SAMPLE_REGS_ABI_64;
}
void perf_get_regs_user(struct perf_regs *regs_user,
struct pt_regs *regs)
{
regs_user->regs = task_pt_regs(current);
regs_user->abi = perf_reg_abi(current);
}
+2
View File
@@ -31,6 +31,7 @@
#include <linux/uaccess.h>
#include <linux/kdebug.h>
#include <linux/kfence.h>
#include <linux/perf_event.h>
#include <asm/assembly.h>
#include <asm/io.h>
@@ -633,6 +634,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
/* Assist Exception Trap, i.e. floating point exception. */
die_if_kernel("Floating point exception", regs, 0); /* quiet */
__inc_irq_stat(irq_fpassist_count);
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
handle_fpe(regs);
return;
+2
View File
@@ -13,6 +13,7 @@
#include <linux/uaccess.h>
#include <linux/sysctl.h>
#include <linux/unaligned.h>
#include <linux/perf_event.h>
#include <asm/hardirq.h>
#include <asm/traps.h>
#include "unaligned.h"
@@ -378,6 +379,7 @@ void handle_unaligned(struct pt_regs *regs)
int ret = ERR_NOTHANDLED;
__inc_irq_stat(irq_unaligned_count);
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->ior);
/* log a message with pacing */
if (user_mode(regs)) {
-1
View File
@@ -41,7 +41,6 @@ unsigned long raw_copy_from_user(void *dst, const void __user *src,
mtsp(get_kernel_space(), SR_TEMP2);
/* Check region is user accessible */
if (start)
while (start < end) {
if (!prober_user(SR_TEMP1, start)) {
newlen = (start - (unsigned long) src);
+2 -3
View File
@@ -1319,7 +1319,7 @@ static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
}
/**
* bio_iov_iter_get_pages_aligned - add user or kernel pages to a bio
* bio_iov_iter_get_pages - add user or kernel pages to a bio
* @bio: bio to add pages to
* @iter: iov iterator describing the region to be added
* @len_align_mask: the mask to align the total size to, 0 for any length
@@ -1339,7 +1339,7 @@ static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
* MM encounters an error pinning the requested pages, it stops. Error
* is returned only if 0 pages could be pinned.
*/
int bio_iov_iter_get_pages_aligned(struct bio *bio, struct iov_iter *iter,
int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
unsigned len_align_mask)
{
int ret = 0;
@@ -1363,7 +1363,6 @@ int bio_iov_iter_get_pages_aligned(struct bio *bio, struct iov_iter *iter,
return bio_iov_iter_align_down(bio, iter, len_align_mask);
return ret;
}
EXPORT_SYMBOL_GPL(bio_iov_iter_get_pages_aligned);
static void submit_bio_wait_endio(struct bio *bio)
{
+5 -1
View File
@@ -283,7 +283,11 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
bio = blk_rq_map_bio_alloc(rq, nr_vecs, gfp_mask);
if (!bio)
return -ENOMEM;
ret = bio_iov_iter_get_pages(bio, iter);
/*
* No alignment requirements on our part to support arbitrary
* passthrough commands.
*/
ret = bio_iov_iter_get_pages(bio, iter, 0);
if (ret)
goto out_put;
ret = blk_rq_append_bio(rq, bio);
+10 -3
View File
@@ -43,6 +43,13 @@ static bool blkdev_dio_invalid(struct block_device *bdev, struct kiocb *iocb,
(bdev_logical_block_size(bdev) - 1);
}
static inline int blkdev_iov_iter_get_pages(struct bio *bio,
struct iov_iter *iter, struct block_device *bdev)
{
return bio_iov_iter_get_pages(bio, iter,
bdev_logical_block_size(bdev) - 1);
}
#define DIO_INLINE_BIO_VECS 4
static ssize_t __blkdev_direct_IO_simple(struct kiocb *iocb,
@@ -78,7 +85,7 @@ static ssize_t __blkdev_direct_IO_simple(struct kiocb *iocb,
if (iocb->ki_flags & IOCB_ATOMIC)
bio.bi_opf |= REQ_ATOMIC;
ret = bio_iov_iter_get_bdev_pages(&bio, iter, bdev);
ret = blkdev_iov_iter_get_pages(&bio, iter, bdev);
if (unlikely(ret))
goto out;
ret = bio.bi_iter.bi_size;
@@ -212,7 +219,7 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
bio->bi_end_io = blkdev_bio_end_io;
bio->bi_ioprio = iocb->ki_ioprio;
ret = bio_iov_iter_get_bdev_pages(bio, iter, bdev);
ret = blkdev_iov_iter_get_pages(bio, iter, bdev);
if (unlikely(ret)) {
bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
@@ -348,7 +355,7 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
*/
bio_iov_bvec_set(bio, iter);
} else {
ret = bio_iov_iter_get_bdev_pages(bio, iter, bdev);
ret = blkdev_iov_iter_get_pages(bio, iter, bdev);
if (unlikely(ret))
goto out_bio_put;
}
+6 -8
View File
@@ -186,9 +186,14 @@ static int essiv_aead_crypt(struct aead_request *req, bool enc)
const struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
struct aead_request *subreq = &rctx->aead_req;
int ivsize = crypto_aead_ivsize(tfm);
int ssize = req->assoclen - ivsize;
struct scatterlist *src = req->src;
int err;
if (ssize < 0)
return -EINVAL;
crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv);
/*
@@ -198,19 +203,12 @@ static int essiv_aead_crypt(struct aead_request *req, bool enc)
*/
rctx->assoc = NULL;
if (req->src == req->dst || !enc) {
scatterwalk_map_and_copy(req->iv, req->dst,
req->assoclen - crypto_aead_ivsize(tfm),
crypto_aead_ivsize(tfm), 1);
scatterwalk_map_and_copy(req->iv, req->dst, ssize, ivsize, 1);
} else {
u8 *iv = (u8 *)aead_request_ctx(req) + tctx->ivoffset;
int ivsize = crypto_aead_ivsize(tfm);
int ssize = req->assoclen - ivsize;
struct scatterlist *sg;
int nents;
if (ssize < 0)
return -EINVAL;
nents = sg_nents_for_len(req->src, ssize);
if (nents < 0)
return -EINVAL;
+2
View File
@@ -294,6 +294,8 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm)
return crypto_init_lskcipher_ops_sg(tfm);
}
crypto_skcipher_set_reqsize(skcipher, crypto_tfm_alg_reqsize(tfm));
if (alg->exit)
skcipher->base.exit = crypto_skcipher_exit_tfm;
+7 -3
View File
@@ -542,8 +542,10 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
return -EBADF;
error = loop_check_backing_file(file);
if (error)
if (error) {
fput(file);
return error;
}
/* suppress uevents while reconfiguring the device */
dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1);
@@ -813,7 +815,7 @@ static void loop_queue_work(struct loop_device *lo, struct loop_cmd *cmd)
if (worker)
goto queue_work;
worker = kzalloc(sizeof(struct loop_worker), GFP_NOWAIT | __GFP_NOWARN);
worker = kzalloc(sizeof(struct loop_worker), GFP_NOWAIT);
/*
* In the event we cannot allocate a worker, just queue on the
* rootcg worker and issue the I/O as the rootcg
@@ -985,8 +987,10 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
return -EBADF;
error = loop_check_backing_file(file);
if (error)
if (error) {
fput(file);
return error;
}
is_loop = is_loop_device(file);
+2 -1
View File
@@ -29,10 +29,11 @@ if TCG_TPM
config TCG_TPM2_HMAC
bool "Use HMAC and encrypted transactions on the TPM bus"
default X86_64
default n
select CRYPTO_ECDH
select CRYPTO_LIB_AESCFB
select CRYPTO_LIB_SHA256
select CRYPTO_LIB_UTILS
help
Setting this causes us to deploy a scheme which uses request
and response HMACs in addition to encryption for
+1 -1
View File
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(suspend_pcr,
unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
{
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return tpm2_calc_ordinal_duration(chip, ordinal);
return tpm2_calc_ordinal_duration(ordinal);
else
return tpm1_calc_ordinal_duration(chip, ordinal);
}
+1 -1
View File
@@ -299,7 +299,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
int tpm2_auto_startup(struct tpm_chip *chip);
void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
unsigned long tpm2_calc_ordinal_duration(u32 ordinal);
int tpm2_probe(struct tpm_chip *chip);
int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip);
int tpm2_find_cc(struct tpm_chip *chip, u32 cc);
+32 -95
View File
@@ -28,120 +28,57 @@ static struct tpm2_hash tpm2_hash_map[] = {
int tpm2_get_timeouts(struct tpm_chip *chip)
{
/* Fixed timeouts for TPM2 */
chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
/* PTP spec timeouts */
chip->duration[TPM_SHORT] = msecs_to_jiffies(TPM2_DURATION_SHORT);
chip->duration[TPM_MEDIUM] = msecs_to_jiffies(TPM2_DURATION_MEDIUM);
chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG);
/* Key creation commands long timeouts */
chip->duration[TPM_LONG_LONG] =
msecs_to_jiffies(TPM2_DURATION_LONG_LONG);
chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
return 0;
}
/**
* tpm2_ordinal_duration_index() - returns an index to the chip duration table
* @ordinal: TPM command ordinal.
*
* The function returns an index to the chip duration table
* (enum tpm_duration), that describes the maximum amount of
* time the chip could take to return the result for a particular ordinal.
*
* The values of the MEDIUM, and LONG durations are taken
* from the PC Client Profile (PTP) specification (750, 2000 msec)
*
* LONG_LONG is for commands that generates keys which empirically takes
* a longer time on some systems.
*
* Return:
* * TPM_MEDIUM
* * TPM_LONG
* * TPM_LONG_LONG
* * TPM_UNDEFINED
/*
* Contains the maximum durations in milliseconds for TPM2 commands.
*/
static u8 tpm2_ordinal_duration_index(u32 ordinal)
{
switch (ordinal) {
/* Startup */
case TPM2_CC_STARTUP: /* 144 */
return TPM_MEDIUM;
case TPM2_CC_SELF_TEST: /* 143 */
return TPM_LONG;
case TPM2_CC_GET_RANDOM: /* 17B */
return TPM_LONG;
case TPM2_CC_SEQUENCE_UPDATE: /* 15C */
return TPM_MEDIUM;
case TPM2_CC_SEQUENCE_COMPLETE: /* 13E */
return TPM_MEDIUM;
case TPM2_CC_EVENT_SEQUENCE_COMPLETE: /* 185 */
return TPM_MEDIUM;
case TPM2_CC_HASH_SEQUENCE_START: /* 186 */
return TPM_MEDIUM;
case TPM2_CC_VERIFY_SIGNATURE: /* 177 */
return TPM_LONG_LONG;
case TPM2_CC_PCR_EXTEND: /* 182 */
return TPM_MEDIUM;
case TPM2_CC_HIERARCHY_CONTROL: /* 121 */
return TPM_LONG;
case TPM2_CC_HIERARCHY_CHANGE_AUTH: /* 129 */
return TPM_LONG;
case TPM2_CC_GET_CAPABILITY: /* 17A */
return TPM_MEDIUM;
case TPM2_CC_NV_READ: /* 14E */
return TPM_LONG;
case TPM2_CC_CREATE_PRIMARY: /* 131 */
return TPM_LONG_LONG;
case TPM2_CC_CREATE: /* 153 */
return TPM_LONG_LONG;
case TPM2_CC_CREATE_LOADED: /* 191 */
return TPM_LONG_LONG;
default:
return TPM_UNDEFINED;
}
}
static const struct {
unsigned long ordinal;
unsigned long duration;
} tpm2_ordinal_duration_map[] = {
{TPM2_CC_STARTUP, 750},
{TPM2_CC_SELF_TEST, 3000},
{TPM2_CC_GET_RANDOM, 2000},
{TPM2_CC_SEQUENCE_UPDATE, 750},
{TPM2_CC_SEQUENCE_COMPLETE, 750},
{TPM2_CC_EVENT_SEQUENCE_COMPLETE, 750},
{TPM2_CC_HASH_SEQUENCE_START, 750},
{TPM2_CC_VERIFY_SIGNATURE, 30000},
{TPM2_CC_PCR_EXTEND, 750},
{TPM2_CC_HIERARCHY_CONTROL, 2000},
{TPM2_CC_HIERARCHY_CHANGE_AUTH, 2000},
{TPM2_CC_GET_CAPABILITY, 750},
{TPM2_CC_NV_READ, 2000},
{TPM2_CC_CREATE_PRIMARY, 30000},
{TPM2_CC_CREATE, 30000},
{TPM2_CC_CREATE_LOADED, 30000},
};
/**
* tpm2_calc_ordinal_duration() - calculate the maximum command duration
* @chip: TPM chip to use.
* tpm2_calc_ordinal_duration() - Calculate the maximum command duration
* @ordinal: TPM command ordinal.
*
* The function returns the maximum amount of time the chip could take
* to return the result for a particular ordinal in jiffies.
*
* Return: A maximal duration time for an ordinal in jiffies.
* Returns the maximum amount of time the chip is expected by kernel to
* take in jiffies.
*/
unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
unsigned long tpm2_calc_ordinal_duration(u32 ordinal)
{
unsigned int index;
int i;
index = tpm2_ordinal_duration_index(ordinal);
for (i = 0; i < ARRAY_SIZE(tpm2_ordinal_duration_map); i++)
if (ordinal == tpm2_ordinal_duration_map[i].ordinal)
return msecs_to_jiffies(tpm2_ordinal_duration_map[i].duration);
if (index != TPM_UNDEFINED)
return chip->duration[index];
else
return msecs_to_jiffies(TPM2_DURATION_DEFAULT);
return msecs_to_jiffies(TPM2_DURATION_DEFAULT);
}
struct tpm2_pcr_read_out {
__be32 update_cnt;
__be32 pcr_selects_cnt;
+30 -74
View File
@@ -69,8 +69,8 @@
#include <linux/unaligned.h>
#include <crypto/kpp.h>
#include <crypto/ecdh.h>
#include <crypto/hash.h>
#include <crypto/hmac.h>
#include <crypto/sha2.h>
#include <crypto/utils.h>
/* maximum number of names the TPM must remember for authorization */
#define AUTH_MAX_NAMES 3
@@ -384,51 +384,6 @@ EXPORT_SYMBOL_GPL(tpm_buf_append_hmac_session);
static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
u32 *handle, u8 *name);
/*
* It turns out the crypto hmac(sha256) is hard for us to consume
* because it assumes a fixed key and the TPM seems to change the key
* on every operation, so we weld the hmac init and final functions in
* here to give it the same usage characteristics as a regular hash
*/
static void tpm2_hmac_init(struct sha256_ctx *sctx, u8 *key, u32 key_len)
{
u8 pad[SHA256_BLOCK_SIZE];
int i;
sha256_init(sctx);
for (i = 0; i < sizeof(pad); i++) {
if (i < key_len)
pad[i] = key[i];
else
pad[i] = 0;
pad[i] ^= HMAC_IPAD_VALUE;
}
sha256_update(sctx, pad, sizeof(pad));
}
static void tpm2_hmac_final(struct sha256_ctx *sctx, u8 *key, u32 key_len,
u8 *out)
{
u8 pad[SHA256_BLOCK_SIZE];
int i;
for (i = 0; i < sizeof(pad); i++) {
if (i < key_len)
pad[i] = key[i];
else
pad[i] = 0;
pad[i] ^= HMAC_OPAD_VALUE;
}
/* collect the final hash; use out as temporary storage */
sha256_final(sctx, out);
sha256_init(sctx);
sha256_update(sctx, pad, sizeof(pad));
sha256_update(sctx, out, SHA256_DIGEST_SIZE);
sha256_final(sctx, out);
}
/*
* assume hash sha256 and nonces u, v of size SHA256_DIGEST_SIZE but
* otherwise standard tpm2_KDFa. Note output is in bytes not bits.
@@ -440,16 +395,16 @@ static void tpm2_KDFa(u8 *key, u32 key_len, const char *label, u8 *u,
const __be32 bits = cpu_to_be32(bytes * 8);
while (bytes > 0) {
struct sha256_ctx sctx;
struct hmac_sha256_ctx hctx;
__be32 c = cpu_to_be32(counter);
tpm2_hmac_init(&sctx, key, key_len);
sha256_update(&sctx, (u8 *)&c, sizeof(c));
sha256_update(&sctx, label, strlen(label)+1);
sha256_update(&sctx, u, SHA256_DIGEST_SIZE);
sha256_update(&sctx, v, SHA256_DIGEST_SIZE);
sha256_update(&sctx, (u8 *)&bits, sizeof(bits));
tpm2_hmac_final(&sctx, key, key_len, out);
hmac_sha256_init_usingrawkey(&hctx, key, key_len);
hmac_sha256_update(&hctx, (u8 *)&c, sizeof(c));
hmac_sha256_update(&hctx, label, strlen(label) + 1);
hmac_sha256_update(&hctx, u, SHA256_DIGEST_SIZE);
hmac_sha256_update(&hctx, v, SHA256_DIGEST_SIZE);
hmac_sha256_update(&hctx, (u8 *)&bits, sizeof(bits));
hmac_sha256_final(&hctx, out);
bytes -= SHA256_DIGEST_SIZE;
counter++;
@@ -593,6 +548,7 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
u32 attrs;
u8 cphash[SHA256_DIGEST_SIZE];
struct sha256_ctx sctx;
struct hmac_sha256_ctx hctx;
if (!auth)
return;
@@ -704,14 +660,14 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
sha256_final(&sctx, cphash);
/* now calculate the hmac */
tpm2_hmac_init(&sctx, auth->session_key, sizeof(auth->session_key)
+ auth->passphrase_len);
sha256_update(&sctx, cphash, sizeof(cphash));
sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce));
sha256_update(&sctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
sha256_update(&sctx, &auth->attrs, 1);
tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key)
+ auth->passphrase_len, hmac);
hmac_sha256_init_usingrawkey(&hctx, auth->session_key,
sizeof(auth->session_key) +
auth->passphrase_len);
hmac_sha256_update(&hctx, cphash, sizeof(cphash));
hmac_sha256_update(&hctx, auth->our_nonce, sizeof(auth->our_nonce));
hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
hmac_sha256_update(&hctx, &auth->attrs, 1);
hmac_sha256_final(&hctx, hmac);
}
EXPORT_SYMBOL(tpm_buf_fill_hmac_session);
@@ -751,6 +707,7 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
u8 rphash[SHA256_DIGEST_SIZE];
u32 attrs, cc;
struct sha256_ctx sctx;
struct hmac_sha256_ctx hctx;
u16 tag = be16_to_cpu(head->tag);
int parm_len, len, i, handles;
@@ -820,21 +777,20 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
sha256_final(&sctx, rphash);
/* now calculate the hmac */
tpm2_hmac_init(&sctx, auth->session_key, sizeof(auth->session_key)
+ auth->passphrase_len);
sha256_update(&sctx, rphash, sizeof(rphash));
sha256_update(&sctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce));
sha256_update(&sctx, &auth->attrs, 1);
hmac_sha256_init_usingrawkey(&hctx, auth->session_key,
sizeof(auth->session_key) +
auth->passphrase_len);
hmac_sha256_update(&hctx, rphash, sizeof(rphash));
hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
hmac_sha256_update(&hctx, auth->our_nonce, sizeof(auth->our_nonce));
hmac_sha256_update(&hctx, &auth->attrs, 1);
/* we're done with the rphash, so put our idea of the hmac there */
tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key)
+ auth->passphrase_len, rphash);
if (memcmp(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE) == 0) {
rc = 0;
} else {
hmac_sha256_final(&hctx, rphash);
if (crypto_memneq(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE)) {
dev_err(&chip->dev, "TPM: HMAC check failed\n");
goto out;
}
rc = 0;
/* now do response decryption */
if (auth->attrs & TPM2_SA_ENCRYPT) {
+66 -23
View File
@@ -33,6 +33,20 @@ static const guid_t tpm_ppi_guid =
GUID_INIT(0x3DDDFAA6, 0x361B, 0x4EB4,
0xA4, 0x24, 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53);
static const char * const tpm_ppi_info[] = {
"Not implemented",
"BIOS only",
"Blocked for OS by system firmware",
"User required",
"User not required",
};
/* A spinlock to protect access to the cache from concurrent reads */
static DEFINE_MUTEX(tpm_ppi_lock);
static u32 ppi_operations_cache[PPI_VS_REQ_END + 1];
static bool ppi_cache_populated;
static bool tpm_ppi_req_has_parameter(u64 req)
{
return req == 23;
@@ -277,8 +291,7 @@ cleanup:
return status;
}
static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
u32 end)
static ssize_t cache_ppi_operations(acpi_handle dev_handle, char *buf)
{
int i;
u32 ret;
@@ -286,34 +299,22 @@ static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
union acpi_object *obj, tmp;
union acpi_object argv = ACPI_INIT_DSM_ARGV4(1, &tmp);
static char *info[] = {
"Not implemented",
"BIOS only",
"Blocked for OS by BIOS",
"User required",
"User not required",
};
if (!acpi_check_dsm(dev_handle, &tpm_ppi_guid, TPM_PPI_REVISION_ID_1,
1 << TPM_PPI_FN_GETOPR))
return -EPERM;
tmp.integer.type = ACPI_TYPE_INTEGER;
for (i = start; i <= end; i++) {
for (i = 0; i <= PPI_VS_REQ_END; i++) {
tmp.integer.value = i;
obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR,
ACPI_TYPE_INTEGER, &argv,
TPM_PPI_REVISION_ID_1);
if (!obj) {
if (!obj)
return -ENOMEM;
} else {
ret = obj->integer.value;
ACPI_FREE(obj);
}
if (ret > 0 && ret < ARRAY_SIZE(info))
len += sysfs_emit_at(buf, len, "%d %d: %s\n",
i, ret, info[ret]);
ret = obj->integer.value;
ppi_operations_cache[i] = ret;
ACPI_FREE(obj);
}
return len;
@@ -324,9 +325,30 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
char *buf)
{
struct tpm_chip *chip = to_tpm_chip(dev);
ssize_t len = 0;
u32 ret;
int i;
return show_ppi_operations(chip->acpi_dev_handle, buf, 0,
PPI_TPM_REQ_MAX);
mutex_lock(&tpm_ppi_lock);
if (!ppi_cache_populated) {
len = cache_ppi_operations(chip->acpi_dev_handle, buf);
if (len < 0) {
mutex_unlock(&tpm_ppi_lock);
return len;
}
ppi_cache_populated = true;
}
for (i = 0; i <= PPI_TPM_REQ_MAX; i++) {
ret = ppi_operations_cache[i];
if (ret >= 0 && ret < ARRAY_SIZE(tpm_ppi_info))
len += sysfs_emit_at(buf, len, "%d %d: %s\n",
i, ret, tpm_ppi_info[ret]);
}
mutex_unlock(&tpm_ppi_lock);
return len;
}
static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
@@ -334,9 +356,30 @@ static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
char *buf)
{
struct tpm_chip *chip = to_tpm_chip(dev);
ssize_t len = 0;
u32 ret;
int i;
return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START,
PPI_VS_REQ_END);
mutex_lock(&tpm_ppi_lock);
if (!ppi_cache_populated) {
len = cache_ppi_operations(chip->acpi_dev_handle, buf);
if (len < 0) {
mutex_unlock(&tpm_ppi_lock);
return len;
}
ppi_cache_populated = true;
}
for (i = PPI_VS_REQ_START; i <= PPI_VS_REQ_END; i++) {
ret = ppi_operations_cache[i];
if (ret >= 0 && ret < ARRAY_SIZE(tpm_ppi_info))
len += sysfs_emit_at(buf, len, "%d %d: %s\n",
i, ret, tpm_ppi_info[ret]);
}
mutex_unlock(&tpm_ppi_lock);
return len;
}
static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
+2 -2
View File
@@ -978,8 +978,8 @@ restore_irqs:
* will call disable_irq which undoes all of the above.
*/
if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
tpm_tis_write8(priv, original_int_vec,
TPM_INT_VECTOR(priv->locality));
tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality),
original_int_vec);
rc = -1;
}
+1
View File
@@ -29,6 +29,7 @@ static const struct acpi_device_id usbio_gpio_acpi_hids[] = {
{ "INTC1007" }, /* MTL */
{ "INTC10B2" }, /* ARL */
{ "INTC10B5" }, /* LNL */
{ "INTC10D1" }, /* MTL-CVF */
{ "INTC10E2" }, /* PTL */
{ }
};
+1 -1
View File
@@ -103,7 +103,7 @@ static int wcd_gpio_probe(struct platform_device *pdev)
chip->base = -1;
chip->ngpio = WCD934X_NPINS;
chip->label = dev_name(dev);
chip->can_sleep = false;
chip->can_sleep = true;
return devm_gpiochip_add_data(dev, chip, data);
}
+1 -1
View File
@@ -30,7 +30,7 @@ static int i2c_debug;
#define pca_clock(adap) adap->i2c_clock
#define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
#define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
#define pca_wait(adap) adap->wait_for_completion(adap->data)
#define pca_wait(adap) adap->wait_for_completion_cb(adap->data)
static void pca_reset(struct i2c_algo_pca_data *adap)
{
+2 -9
View File
@@ -868,7 +868,7 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
return 0;
}
static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
static void mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
{
unsigned int clk_src;
unsigned int step_cnt;
@@ -938,9 +938,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
break;
}
return 0;
}
static void i2c_dump_register(struct mtk_i2c *i2c)
@@ -1460,11 +1457,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
strscpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
ret = mtk_i2c_set_speed(i2c, clk_get_rate(i2c->clocks[speed_clk].clk));
if (ret) {
dev_err(&pdev->dev, "Failed to set the speed.\n");
return -EINVAL;
}
mtk_i2c_set_speed(i2c, clk_get_rate(i2c->clocks[speed_clk].clk));
if (i2c->dev_comp->max_dma_support > 32) {
ret = dma_set_mask(&pdev->dev,
+1 -1
View File
@@ -95,7 +95,7 @@ static struct i2c_algo_pca_data pca_isa_data = {
/* .data intentionally left NULL, not needed with ISA */
.write_byte = pca_isa_writebyte,
.read_byte = pca_isa_readbyte,
.wait_for_completion = pca_isa_waitforcompletion,
.wait_for_completion_cb = pca_isa_waitforcompletion,
.reset_chip = pca_isa_resetchip,
};
+1 -1
View File
@@ -180,7 +180,7 @@ static int i2c_pca_pf_probe(struct platform_device *pdev)
}
i2c->algo_data.data = i2c;
i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
i2c->algo_data.wait_for_completion_cb = i2c_pca_pf_waitforcompletion;
if (i2c->gpio)
i2c->algo_data.reset_chip = i2c_pca_pf_resetchip;
else
+295 -176
View File
@@ -8,6 +8,7 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/unaligned.h>
enum rtl9300_bus_freq {
RTL9300_I2C_STD_FREQ,
@@ -20,103 +21,143 @@ struct rtl9300_i2c_chan {
struct i2c_adapter adap;
struct rtl9300_i2c *i2c;
enum rtl9300_bus_freq bus_freq;
u8 sda_pin;
u8 sda_num;
};
enum rtl9300_i2c_reg_scope {
REG_SCOPE_GLOBAL,
REG_SCOPE_MASTER,
};
struct rtl9300_i2c_reg_field {
struct reg_field field;
enum rtl9300_i2c_reg_scope scope;
};
enum rtl9300_i2c_reg_fields {
F_DATA_WIDTH = 0,
F_DEV_ADDR,
F_I2C_FAIL,
F_I2C_TRIG,
F_MEM_ADDR,
F_MEM_ADDR_WIDTH,
F_RD_MODE,
F_RWOP,
F_SCL_FREQ,
F_SCL_SEL,
F_SDA_OUT_SEL,
F_SDA_SEL,
/* keep last */
F_NUM_FIELDS
};
struct rtl9300_i2c_drv_data {
struct rtl9300_i2c_reg_field field_desc[F_NUM_FIELDS];
int (*select_scl)(struct rtl9300_i2c *i2c, u8 scl);
u32 data_reg;
u8 max_nchan;
};
#define RTL9300_I2C_MUX_NCHAN 8
#define RTL9310_I2C_MUX_NCHAN 12
struct rtl9300_i2c {
struct regmap *regmap;
struct device *dev;
struct rtl9300_i2c_chan chans[RTL9300_I2C_MUX_NCHAN];
struct rtl9300_i2c_chan chans[RTL9310_I2C_MUX_NCHAN];
struct regmap_field *fields[F_NUM_FIELDS];
u32 reg_base;
u8 sda_pin;
u32 data_reg;
u8 scl_num;
u8 sda_num;
struct mutex lock;
};
DEFINE_GUARD(rtl9300_i2c, struct rtl9300_i2c *, mutex_lock(&_T->lock), mutex_unlock(&_T->lock))
enum rtl9300_i2c_xfer_type {
RTL9300_I2C_XFER_BYTE,
RTL9300_I2C_XFER_WORD,
RTL9300_I2C_XFER_BLOCK,
};
struct rtl9300_i2c_xfer {
enum rtl9300_i2c_xfer_type type;
u16 dev_addr;
u8 reg_addr;
u8 reg_addr_len;
u8 *data;
u8 data_len;
bool write;
};
#define RTL9300_I2C_MST_CTRL1 0x0
#define RTL9300_I2C_MST_CTRL1_MEM_ADDR_OFS 8
#define RTL9300_I2C_MST_CTRL1_MEM_ADDR_MASK GENMASK(31, 8)
#define RTL9300_I2C_MST_CTRL1_SDA_OUT_SEL_OFS 4
#define RTL9300_I2C_MST_CTRL1_SDA_OUT_SEL_MASK GENMASK(6, 4)
#define RTL9300_I2C_MST_CTRL1_GPIO_SCL_SEL BIT(3)
#define RTL9300_I2C_MST_CTRL1_RWOP BIT(2)
#define RTL9300_I2C_MST_CTRL1_I2C_FAIL BIT(1)
#define RTL9300_I2C_MST_CTRL1_I2C_TRIG BIT(0)
#define RTL9300_I2C_MST_CTRL2 0x4
#define RTL9300_I2C_MST_CTRL2_RD_MODE BIT(15)
#define RTL9300_I2C_MST_CTRL2_DEV_ADDR_OFS 8
#define RTL9300_I2C_MST_CTRL2_DEV_ADDR_MASK GENMASK(14, 8)
#define RTL9300_I2C_MST_CTRL2_DATA_WIDTH_OFS 4
#define RTL9300_I2C_MST_CTRL2_DATA_WIDTH_MASK GENMASK(7, 4)
#define RTL9300_I2C_MST_CTRL2_MEM_ADDR_WIDTH_OFS 2
#define RTL9300_I2C_MST_CTRL2_MEM_ADDR_WIDTH_MASK GENMASK(3, 2)
#define RTL9300_I2C_MST_CTRL2_SCL_FREQ_OFS 0
#define RTL9300_I2C_MST_CTRL2_SCL_FREQ_MASK GENMASK(1, 0)
#define RTL9300_I2C_MST_DATA_WORD0 0x8
#define RTL9300_I2C_MST_DATA_WORD1 0xc
#define RTL9300_I2C_MST_DATA_WORD2 0x10
#define RTL9300_I2C_MST_DATA_WORD3 0x14
#define RTL9300_I2C_MST_GLB_CTRL 0x384
#define RTL9310_I2C_MST_IF_CTRL 0x1004
#define RTL9310_I2C_MST_IF_SEL 0x1008
#define RTL9310_I2C_MST_CTRL 0x0
#define RTL9310_I2C_MST_MEMADDR_CTRL 0x4
#define RTL9310_I2C_MST_DATA_CTRL 0x8
static int rtl9300_i2c_reg_addr_set(struct rtl9300_i2c *i2c, u32 reg, u16 len)
{
u32 val, mask;
int ret;
val = len << RTL9300_I2C_MST_CTRL2_MEM_ADDR_WIDTH_OFS;
mask = RTL9300_I2C_MST_CTRL2_MEM_ADDR_WIDTH_MASK;
ret = regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL2, mask, val);
ret = regmap_field_write(i2c->fields[F_MEM_ADDR_WIDTH], len);
if (ret)
return ret;
val = reg << RTL9300_I2C_MST_CTRL1_MEM_ADDR_OFS;
mask = RTL9300_I2C_MST_CTRL1_MEM_ADDR_MASK;
return regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, mask, val);
return regmap_field_write(i2c->fields[F_MEM_ADDR], reg);
}
static int rtl9300_i2c_config_io(struct rtl9300_i2c *i2c, u8 sda_pin)
static int rtl9300_i2c_select_scl(struct rtl9300_i2c *i2c, u8 scl)
{
int ret;
u32 val, mask;
return regmap_field_write(i2c->fields[F_SCL_SEL], 1);
}
ret = regmap_update_bits(i2c->regmap, RTL9300_I2C_MST_GLB_CTRL, BIT(sda_pin), BIT(sda_pin));
static int rtl9310_i2c_select_scl(struct rtl9300_i2c *i2c, u8 scl)
{
return regmap_field_update_bits(i2c->fields[F_SCL_SEL], BIT(scl), BIT(scl));
}
static int rtl9300_i2c_config_chan(struct rtl9300_i2c *i2c, struct rtl9300_i2c_chan *chan)
{
struct rtl9300_i2c_drv_data *drv_data;
int ret;
if (i2c->sda_num == chan->sda_num)
return 0;
ret = regmap_field_write(i2c->fields[F_SCL_FREQ], chan->bus_freq);
if (ret)
return ret;
val = (sda_pin << RTL9300_I2C_MST_CTRL1_SDA_OUT_SEL_OFS) |
RTL9300_I2C_MST_CTRL1_GPIO_SCL_SEL;
mask = RTL9300_I2C_MST_CTRL1_SDA_OUT_SEL_MASK | RTL9300_I2C_MST_CTRL1_GPIO_SCL_SEL;
drv_data = (struct rtl9300_i2c_drv_data *)device_get_match_data(i2c->dev);
ret = drv_data->select_scl(i2c, i2c->scl_num);
if (ret)
return ret;
return regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, mask, val);
ret = regmap_field_update_bits(i2c->fields[F_SDA_SEL], BIT(chan->sda_num),
BIT(chan->sda_num));
if (ret)
return ret;
ret = regmap_field_write(i2c->fields[F_SDA_OUT_SEL], chan->sda_num);
if (ret)
return ret;
i2c->sda_num = chan->sda_num;
return 0;
}
static int rtl9300_i2c_config_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_chan *chan,
u16 addr, u16 len)
{
u32 val, mask;
if (len < 1 || len > 16)
return -EINVAL;
val = chan->bus_freq << RTL9300_I2C_MST_CTRL2_SCL_FREQ_OFS;
mask = RTL9300_I2C_MST_CTRL2_SCL_FREQ_MASK;
val |= addr << RTL9300_I2C_MST_CTRL2_DEV_ADDR_OFS;
mask |= RTL9300_I2C_MST_CTRL2_DEV_ADDR_MASK;
val |= ((len - 1) & 0xf) << RTL9300_I2C_MST_CTRL2_DATA_WIDTH_OFS;
mask |= RTL9300_I2C_MST_CTRL2_DATA_WIDTH_MASK;
mask |= RTL9300_I2C_MST_CTRL2_RD_MODE;
return regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL2, mask, val);
}
static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, int len)
static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, u8 len)
{
u32 vals[4] = {};
int i, ret;
@@ -124,8 +165,7 @@ static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, int len)
if (len > 16)
return -EIO;
ret = regmap_bulk_read(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0,
vals, ARRAY_SIZE(vals));
ret = regmap_bulk_read(i2c->regmap, i2c->data_reg, vals, ARRAY_SIZE(vals));
if (ret)
return ret;
@@ -137,7 +177,7 @@ static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, int len)
return 0;
}
static int rtl9300_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, int len)
static int rtl9300_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, u8 len)
{
u32 vals[4] = {};
int i;
@@ -152,56 +192,94 @@ static int rtl9300_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, int len)
vals[reg] |= buf[i] << shift;
}
return regmap_bulk_write(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0,
vals, ARRAY_SIZE(vals));
return regmap_bulk_write(i2c->regmap, i2c->data_reg, vals, ARRAY_SIZE(vals));
}
static int rtl9300_i2c_writel(struct rtl9300_i2c *i2c, u32 data)
{
return regmap_write(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, data);
return regmap_write(i2c->regmap, i2c->data_reg, data);
}
static int rtl9300_i2c_execute_xfer(struct rtl9300_i2c *i2c, char read_write,
int size, union i2c_smbus_data *data, int len)
static int rtl9300_i2c_prepare_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_xfer *xfer)
{
u32 val, mask;
int ret;
val = read_write == I2C_SMBUS_WRITE ? RTL9300_I2C_MST_CTRL1_RWOP : 0;
mask = RTL9300_I2C_MST_CTRL1_RWOP;
if (xfer->data_len < 1 || xfer->data_len > 16)
return -EINVAL;
val |= RTL9300_I2C_MST_CTRL1_I2C_TRIG;
mask |= RTL9300_I2C_MST_CTRL1_I2C_TRIG;
ret = regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, mask, val);
ret = regmap_field_write(i2c->fields[F_DEV_ADDR], xfer->dev_addr);
if (ret)
return ret;
ret = regmap_read_poll_timeout(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1,
val, !(val & RTL9300_I2C_MST_CTRL1_I2C_TRIG), 100, 100000);
ret = rtl9300_i2c_reg_addr_set(i2c, xfer->reg_addr, xfer->reg_addr_len);
if (ret)
return ret;
if (val & RTL9300_I2C_MST_CTRL1_I2C_FAIL)
ret = regmap_field_write(i2c->fields[F_RWOP], xfer->write);
if (ret)
return ret;
ret = regmap_field_write(i2c->fields[F_DATA_WIDTH], (xfer->data_len - 1) & 0xf);
if (ret)
return ret;
if (xfer->write) {
switch (xfer->type) {
case RTL9300_I2C_XFER_BYTE:
ret = rtl9300_i2c_writel(i2c, *xfer->data);
break;
case RTL9300_I2C_XFER_WORD:
ret = rtl9300_i2c_writel(i2c, get_unaligned((const u16 *)xfer->data));
break;
default:
ret = rtl9300_i2c_write(i2c, xfer->data, xfer->data_len);
break;
}
}
return ret;
}
static int rtl9300_i2c_do_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_xfer *xfer)
{
u32 val;
int ret;
ret = regmap_field_write(i2c->fields[F_I2C_TRIG], 1);
if (ret)
return ret;
ret = regmap_field_read_poll_timeout(i2c->fields[F_I2C_TRIG], val, !val, 100, 100000);
if (ret)
return ret;
ret = regmap_field_read(i2c->fields[F_I2C_FAIL], &val);
if (ret)
return ret;
if (val)
return -EIO;
if (read_write == I2C_SMBUS_READ) {
if (size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA) {
ret = regmap_read(i2c->regmap,
i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, &val);
if (!xfer->write) {
switch (xfer->type) {
case RTL9300_I2C_XFER_BYTE:
ret = regmap_read(i2c->regmap, i2c->data_reg, &val);
if (ret)
return ret;
data->byte = val & 0xff;
} else if (size == I2C_SMBUS_WORD_DATA) {
ret = regmap_read(i2c->regmap,
i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, &val);
*xfer->data = val & 0xff;
break;
case RTL9300_I2C_XFER_WORD:
ret = regmap_read(i2c->regmap, i2c->data_reg, &val);
if (ret)
return ret;
data->word = val & 0xffff;
} else {
ret = rtl9300_i2c_read(i2c, &data->block[0], len);
put_unaligned(val & 0xffff, (u16*)xfer->data);
break;
default:
ret = rtl9300_i2c_read(i2c, xfer->data, xfer->data_len);
if (ret)
return ret;
break;
}
}
@@ -214,100 +292,68 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned s
{
struct rtl9300_i2c_chan *chan = i2c_get_adapdata(adap);
struct rtl9300_i2c *i2c = chan->i2c;
int len = 0, ret;
struct rtl9300_i2c_xfer xfer = {0};
int ret;
mutex_lock(&i2c->lock);
if (chan->sda_pin != i2c->sda_pin) {
ret = rtl9300_i2c_config_io(i2c, chan->sda_pin);
if (ret)
goto out_unlock;
i2c->sda_pin = chan->sda_pin;
}
if (addr > 0x7f)
return -EINVAL;
guard(rtl9300_i2c)(i2c);
ret = rtl9300_i2c_config_chan(i2c, chan);
if (ret)
return ret;
xfer.dev_addr = addr & 0x7f;
xfer.write = (read_write == I2C_SMBUS_WRITE);
xfer.reg_addr = command;
xfer.reg_addr_len = 1;
switch (size) {
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_WRITE) {
ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 0);
if (ret)
goto out_unlock;
ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
if (ret)
goto out_unlock;
} else {
ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 1);
if (ret)
goto out_unlock;
ret = rtl9300_i2c_reg_addr_set(i2c, 0, 0);
if (ret)
goto out_unlock;
}
xfer.data = (read_write == I2C_SMBUS_READ) ? &data->byte : &command;
xfer.data_len = 1;
xfer.reg_addr = 0;
xfer.reg_addr_len = 0;
xfer.type = RTL9300_I2C_XFER_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
if (ret)
goto out_unlock;
ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 1);
if (ret)
goto out_unlock;
if (read_write == I2C_SMBUS_WRITE) {
ret = rtl9300_i2c_writel(i2c, data->byte);
if (ret)
goto out_unlock;
}
xfer.data = &data->byte;
xfer.data_len = 1;
xfer.type = RTL9300_I2C_XFER_BYTE;
break;
case I2C_SMBUS_WORD_DATA:
ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
if (ret)
goto out_unlock;
ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 2);
if (ret)
goto out_unlock;
if (read_write == I2C_SMBUS_WRITE) {
ret = rtl9300_i2c_writel(i2c, data->word);
if (ret)
goto out_unlock;
}
xfer.data = (u8 *)&data->word;
xfer.data_len = 2;
xfer.type = RTL9300_I2C_XFER_WORD;
break;
case I2C_SMBUS_BLOCK_DATA:
ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
if (ret)
goto out_unlock;
if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) {
ret = -EINVAL;
goto out_unlock;
}
ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0] + 1);
if (ret)
goto out_unlock;
if (read_write == I2C_SMBUS_WRITE) {
ret = rtl9300_i2c_write(i2c, &data->block[0], data->block[0] + 1);
if (ret)
goto out_unlock;
}
len = data->block[0] + 1;
xfer.data = &data->block[0];
xfer.data_len = data->block[0] + 1;
xfer.type = RTL9300_I2C_XFER_BLOCK;
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
xfer.data = &data->block[1];
xfer.data_len = data->block[0];
xfer.type = RTL9300_I2C_XFER_BLOCK;
break;
default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
ret = -EOPNOTSUPP;
goto out_unlock;
return -EOPNOTSUPP;
}
ret = rtl9300_i2c_execute_xfer(i2c, read_write, size, data, len);
ret = rtl9300_i2c_prepare_xfer(i2c, &xfer);
if (ret)
return ret;
out_unlock:
mutex_unlock(&i2c->lock);
return ret;
return rtl9300_i2c_do_xfer(i2c, &xfer);
}
static u32 rtl9300_i2c_func(struct i2c_adapter *a)
{
return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA;
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK;
}
static const struct i2c_algorithm rtl9300_i2c_algo = {
@@ -325,9 +371,11 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rtl9300_i2c *i2c;
u32 clock_freq, sda_pin;
int ret, i = 0;
struct fwnode_handle *child;
struct rtl9300_i2c_drv_data *drv_data;
struct reg_field fields[F_NUM_FIELDS];
u32 clock_freq, scl_num, sda_num;
int ret, i = 0;
i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c)
@@ -344,16 +392,34 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
if (ret)
return ret;
ret = device_property_read_u32(dev, "realtek,scl", &scl_num);
if (ret || scl_num != 1)
scl_num = 0;
i2c->scl_num = (u8)scl_num;
platform_set_drvdata(pdev, i2c);
if (device_get_child_node_count(dev) > RTL9300_I2C_MUX_NCHAN)
drv_data = (struct rtl9300_i2c_drv_data *)device_get_match_data(i2c->dev);
if (device_get_child_node_count(dev) > drv_data->max_nchan)
return dev_err_probe(dev, -EINVAL, "Too many channels\n");
i2c->data_reg = i2c->reg_base + drv_data->data_reg;
for (i = 0; i < F_NUM_FIELDS; i++) {
fields[i] = drv_data->field_desc[i].field;
if (drv_data->field_desc[i].scope == REG_SCOPE_MASTER)
fields[i].reg += i2c->reg_base;
}
ret = devm_regmap_field_bulk_alloc(dev, i2c->regmap, i2c->fields,
fields, F_NUM_FIELDS);
if (ret)
return ret;
i = 0;
device_for_each_child_node(dev, child) {
struct rtl9300_i2c_chan *chan = &i2c->chans[i];
struct i2c_adapter *adap = &chan->adap;
ret = fwnode_property_read_u32(child, "reg", &sda_pin);
ret = fwnode_property_read_u32(child, "reg", &sda_num);
if (ret)
return ret;
@@ -365,17 +431,16 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
case I2C_MAX_STANDARD_MODE_FREQ:
chan->bus_freq = RTL9300_I2C_STD_FREQ;
break;
case I2C_MAX_FAST_MODE_FREQ:
chan->bus_freq = RTL9300_I2C_FAST_FREQ;
break;
default:
dev_warn(i2c->dev, "SDA%d clock-frequency %d not supported using default\n",
sda_pin, clock_freq);
sda_num, clock_freq);
break;
}
chan->sda_pin = sda_pin;
chan->sda_num = sda_num;
chan->i2c = i2c;
adap = &i2c->chans[i].adap;
adap->owner = THIS_MODULE;
@@ -385,23 +450,77 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
adap->dev.parent = dev;
i2c_set_adapdata(adap, chan);
adap->dev.of_node = to_of_node(child);
snprintf(adap->name, sizeof(adap->name), "%s SDA%d\n", dev_name(dev), sda_pin);
snprintf(adap->name, sizeof(adap->name), "%s SDA%d\n", dev_name(dev), sda_num);
i++;
ret = devm_i2c_add_adapter(dev, adap);
if (ret)
return ret;
}
i2c->sda_pin = 0xff;
i2c->sda_num = 0xff;
/* only use standard read format */
ret = regmap_field_write(i2c->fields[F_RD_MODE], 0);
if (ret)
return ret;
return 0;
}
#define GLB_REG_FIELD(reg, msb, lsb) \
{ .field = REG_FIELD(reg, msb, lsb), .scope = REG_SCOPE_GLOBAL }
#define MST_REG_FIELD(reg, msb, lsb) \
{ .field = REG_FIELD(reg, msb, lsb), .scope = REG_SCOPE_MASTER }
static const struct rtl9300_i2c_drv_data rtl9300_i2c_drv_data = {
.field_desc = {
[F_MEM_ADDR] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL1, 8, 31),
[F_SDA_OUT_SEL] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL1, 4, 6),
[F_SCL_SEL] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL1, 3, 3),
[F_RWOP] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL1, 2, 2),
[F_I2C_FAIL] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL1, 1, 1),
[F_I2C_TRIG] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL1, 0, 0),
[F_RD_MODE] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 15, 15),
[F_DEV_ADDR] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 8, 14),
[F_DATA_WIDTH] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 4, 7),
[F_MEM_ADDR_WIDTH] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 2, 3),
[F_SCL_FREQ] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 0, 1),
[F_SDA_SEL] = GLB_REG_FIELD(RTL9300_I2C_MST_GLB_CTRL, 0, 7),
},
.select_scl = rtl9300_i2c_select_scl,
.data_reg = RTL9300_I2C_MST_DATA_WORD0,
.max_nchan = RTL9300_I2C_MUX_NCHAN,
};
static const struct rtl9300_i2c_drv_data rtl9310_i2c_drv_data = {
.field_desc = {
[F_SCL_SEL] = GLB_REG_FIELD(RTL9310_I2C_MST_IF_SEL, 12, 13),
[F_SDA_SEL] = GLB_REG_FIELD(RTL9310_I2C_MST_IF_SEL, 0, 11),
[F_SCL_FREQ] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 30, 31),
[F_DEV_ADDR] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 11, 17),
[F_SDA_OUT_SEL] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 18, 21),
[F_MEM_ADDR_WIDTH] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 9, 10),
[F_DATA_WIDTH] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 5, 8),
[F_RD_MODE] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 4, 4),
[F_RWOP] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 2, 2),
[F_I2C_FAIL] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 1, 1),
[F_I2C_TRIG] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 0, 0),
[F_MEM_ADDR] = MST_REG_FIELD(RTL9310_I2C_MST_MEMADDR_CTRL, 0, 23),
},
.select_scl = rtl9310_i2c_select_scl,
.data_reg = RTL9310_I2C_MST_DATA_CTRL,
.max_nchan = RTL9310_I2C_MUX_NCHAN,
};
static const struct of_device_id i2c_rtl9300_dt_ids[] = {
{ .compatible = "realtek,rtl9301-i2c" },
{ .compatible = "realtek,rtl9302b-i2c" },
{ .compatible = "realtek,rtl9302c-i2c" },
{ .compatible = "realtek,rtl9303-i2c" },
{ .compatible = "realtek,rtl9301-i2c", .data = (void *) &rtl9300_i2c_drv_data },
{ .compatible = "realtek,rtl9302b-i2c", .data = (void *) &rtl9300_i2c_drv_data },
{ .compatible = "realtek,rtl9302c-i2c", .data = (void *) &rtl9300_i2c_drv_data },
{ .compatible = "realtek,rtl9303-i2c", .data = (void *) &rtl9300_i2c_drv_data },
{ .compatible = "realtek,rtl9310-i2c", .data = (void *) &rtl9310_i2c_drv_data },
{ .compatible = "realtek,rtl9311-i2c", .data = (void *) &rtl9310_i2c_drv_data },
{ .compatible = "realtek,rtl9312-i2c", .data = (void *) &rtl9310_i2c_drv_data },
{ .compatible = "realtek,rtl9313-i2c", .data = (void *) &rtl9310_i2c_drv_data },
{}
};
MODULE_DEVICE_TABLE(of, i2c_rtl9300_dt_ids);
+17 -1
View File
@@ -197,13 +197,22 @@ static int amd_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
static int amd_ntb_get_link_status(struct amd_ntb_dev *ndev)
{
struct pci_dev *pdev = NULL;
struct pci_dev *pdev = ndev->ntb.pdev;
struct pci_dev *pci_swds = NULL;
struct pci_dev *pci_swus = NULL;
u32 stat;
int rc;
if (ndev->ntb.topo == NTB_TOPO_SEC) {
if (ndev->dev_data->is_endpoint) {
rc = pcie_capability_read_dword(pdev, PCI_EXP_LNKCTL, &stat);
if (rc)
return rc;
ndev->lnk_sta = stat;
return 0;
}
/* Locate the pointer to Downstream Switch for this device */
pci_swds = pci_upstream_bridge(ndev->ntb.pdev);
if (pci_swds) {
@@ -1311,6 +1320,11 @@ static const struct ntb_dev_data dev_data[] = {
.mw_count = 2,
.mw_idx = 2,
},
{ /* for device 0x17d7 */
.mw_count = 2,
.mw_idx = 2,
.is_endpoint = true,
},
};
static const struct pci_device_id amd_ntb_pci_tbl[] = {
@@ -1319,6 +1333,8 @@ static const struct pci_device_id amd_ntb_pci_tbl[] = {
{ PCI_VDEVICE(AMD, 0x14c0), (kernel_ulong_t)&dev_data[1] },
{ PCI_VDEVICE(AMD, 0x14c3), (kernel_ulong_t)&dev_data[1] },
{ PCI_VDEVICE(AMD, 0x155a), (kernel_ulong_t)&dev_data[1] },
{ PCI_VDEVICE(AMD, 0x17d4), (kernel_ulong_t)&dev_data[1] },
{ PCI_VDEVICE(AMD, 0x17d7), (kernel_ulong_t)&dev_data[2] },
{ PCI_VDEVICE(HYGON, 0x145b), (kernel_ulong_t)&dev_data[0] },
{ 0, }
};
+1
View File
@@ -168,6 +168,7 @@ enum {
struct ntb_dev_data {
const unsigned char mw_count;
const unsigned int mw_idx;
const bool is_endpoint;
};
struct amd_ntb_dev;
+68 -50
View File
@@ -49,6 +49,7 @@
#define NTB_EPF_COMMAND_TIMEOUT 1000 /* 1 Sec */
enum pci_barno {
NO_BAR = -1,
BAR_0,
BAR_1,
BAR_2,
@@ -57,16 +58,26 @@ enum pci_barno {
BAR_5,
};
enum epf_ntb_bar {
BAR_CONFIG,
BAR_PEER_SPAD,
BAR_DB,
BAR_MW1,
BAR_MW2,
BAR_MW3,
BAR_MW4,
NTB_BAR_NUM,
};
#define NTB_EPF_MAX_MW_COUNT (NTB_BAR_NUM - BAR_MW1)
struct ntb_epf_dev {
struct ntb_dev ntb;
struct device *dev;
/* Mutex to protect providing commands to NTB EPF */
struct mutex cmd_lock;
enum pci_barno ctrl_reg_bar;
enum pci_barno peer_spad_reg_bar;
enum pci_barno db_reg_bar;
enum pci_barno mw_bar;
const enum pci_barno *barno_map;
unsigned int mw_count;
unsigned int spad_count;
@@ -85,17 +96,6 @@ struct ntb_epf_dev {
#define ntb_ndev(__ntb) container_of(__ntb, struct ntb_epf_dev, ntb)
struct ntb_epf_data {
/* BAR that contains both control region and self spad region */
enum pci_barno ctrl_reg_bar;
/* BAR that contains peer spad region */
enum pci_barno peer_spad_reg_bar;
/* BAR that contains Doorbell region and Memory window '1' */
enum pci_barno db_reg_bar;
/* BAR that contains memory windows*/
enum pci_barno mw_bar;
};
static int ntb_epf_send_command(struct ntb_epf_dev *ndev, u32 command,
u32 argument)
{
@@ -144,7 +144,7 @@ static int ntb_epf_mw_to_bar(struct ntb_epf_dev *ndev, int idx)
return -EINVAL;
}
return idx + 2;
return ndev->barno_map[BAR_MW1 + idx];
}
static int ntb_epf_mw_count(struct ntb_dev *ntb, int pidx)
@@ -413,7 +413,9 @@ static int ntb_epf_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
return -EINVAL;
}
bar = idx + ndev->mw_bar;
bar = ntb_epf_mw_to_bar(ndev, idx);
if (bar < 0)
return bar;
mw_size = pci_resource_len(ntb->pdev, bar);
@@ -455,7 +457,9 @@ static int ntb_epf_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
if (idx == 0)
offset = readl(ndev->ctrl_reg + NTB_EPF_MW1_OFFSET);
bar = idx + ndev->mw_bar;
bar = ntb_epf_mw_to_bar(ndev, idx);
if (bar < 0)
return bar;
if (base)
*base = pci_resource_start(ndev->ntb.pdev, bar) + offset;
@@ -560,6 +564,11 @@ static int ntb_epf_init_dev(struct ntb_epf_dev *ndev)
ndev->mw_count = readl(ndev->ctrl_reg + NTB_EPF_MW_COUNT);
ndev->spad_count = readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT);
if (ndev->mw_count > NTB_EPF_MAX_MW_COUNT) {
dev_err(dev, "Unsupported MW count: %u\n", ndev->mw_count);
return -EINVAL;
}
return 0;
}
@@ -596,14 +605,15 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev,
dev_warn(&pdev->dev, "Cannot DMA highmem\n");
}
ndev->ctrl_reg = pci_iomap(pdev, ndev->ctrl_reg_bar, 0);
ndev->ctrl_reg = pci_iomap(pdev, ndev->barno_map[BAR_CONFIG], 0);
if (!ndev->ctrl_reg) {
ret = -EIO;
goto err_pci_regions;
}
if (ndev->peer_spad_reg_bar) {
ndev->peer_spad_reg = pci_iomap(pdev, ndev->peer_spad_reg_bar, 0);
if (ndev->barno_map[BAR_PEER_SPAD] != ndev->barno_map[BAR_CONFIG]) {
ndev->peer_spad_reg = pci_iomap(pdev,
ndev->barno_map[BAR_PEER_SPAD], 0);
if (!ndev->peer_spad_reg) {
ret = -EIO;
goto err_pci_regions;
@@ -614,7 +624,7 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev,
ndev->peer_spad_reg = ndev->ctrl_reg + spad_off + spad_sz;
}
ndev->db_reg = pci_iomap(pdev, ndev->db_reg_bar, 0);
ndev->db_reg = pci_iomap(pdev, ndev->barno_map[BAR_DB], 0);
if (!ndev->db_reg) {
ret = -EIO;
goto err_pci_regions;
@@ -659,12 +669,7 @@ static void ntb_epf_cleanup_isr(struct ntb_epf_dev *ndev)
static int ntb_epf_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
enum pci_barno peer_spad_reg_bar = BAR_1;
enum pci_barno ctrl_reg_bar = BAR_0;
enum pci_barno db_reg_bar = BAR_2;
enum pci_barno mw_bar = BAR_2;
struct device *dev = &pdev->dev;
struct ntb_epf_data *data;
struct ntb_epf_dev *ndev;
int ret;
@@ -675,18 +680,10 @@ static int ntb_epf_pci_probe(struct pci_dev *pdev,
if (!ndev)
return -ENOMEM;
data = (struct ntb_epf_data *)id->driver_data;
if (data) {
peer_spad_reg_bar = data->peer_spad_reg_bar;
ctrl_reg_bar = data->ctrl_reg_bar;
db_reg_bar = data->db_reg_bar;
mw_bar = data->mw_bar;
}
ndev->barno_map = (const enum pci_barno *)id->driver_data;
if (!ndev->barno_map)
return -EINVAL;
ndev->peer_spad_reg_bar = peer_spad_reg_bar;
ndev->ctrl_reg_bar = ctrl_reg_bar;
ndev->db_reg_bar = db_reg_bar;
ndev->mw_bar = mw_bar;
ndev->dev = dev;
ntb_epf_init_struct(ndev, pdev);
@@ -730,30 +727,51 @@ static void ntb_epf_pci_remove(struct pci_dev *pdev)
ntb_epf_deinit_pci(ndev);
}
static const struct ntb_epf_data j721e_data = {
.ctrl_reg_bar = BAR_0,
.peer_spad_reg_bar = BAR_1,
.db_reg_bar = BAR_2,
.mw_bar = BAR_2,
static const enum pci_barno j721e_map[NTB_BAR_NUM] = {
[BAR_CONFIG] = BAR_0,
[BAR_PEER_SPAD] = BAR_1,
[BAR_DB] = BAR_2,
[BAR_MW1] = BAR_2,
[BAR_MW2] = BAR_3,
[BAR_MW3] = BAR_4,
[BAR_MW4] = BAR_5
};
static const struct ntb_epf_data mx8_data = {
.ctrl_reg_bar = BAR_0,
.peer_spad_reg_bar = BAR_0,
.db_reg_bar = BAR_2,
.mw_bar = BAR_4,
static const enum pci_barno mx8_map[NTB_BAR_NUM] = {
[BAR_CONFIG] = BAR_0,
[BAR_PEER_SPAD] = BAR_0,
[BAR_DB] = BAR_2,
[BAR_MW1] = BAR_4,
[BAR_MW2] = BAR_5,
[BAR_MW3] = NO_BAR,
[BAR_MW4] = NO_BAR
};
static const enum pci_barno rcar_barno[NTB_BAR_NUM] = {
[BAR_CONFIG] = BAR_0,
[BAR_PEER_SPAD] = BAR_0,
[BAR_DB] = BAR_4,
[BAR_MW1] = BAR_2,
[BAR_MW2] = NO_BAR,
[BAR_MW3] = NO_BAR,
[BAR_MW4] = NO_BAR,
};
static const struct pci_device_id ntb_epf_pci_tbl[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721E),
.class = PCI_CLASS_MEMORY_RAM << 8, .class_mask = 0xffff00,
.driver_data = (kernel_ulong_t)&j721e_data,
.driver_data = (kernel_ulong_t)j721e_map,
},
{
PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x0809),
.class = PCI_CLASS_MEMORY_RAM << 8, .class_mask = 0xffff00,
.driver_data = (kernel_ulong_t)&mx8_data,
.driver_data = (kernel_ulong_t)mx8_map,
},
{
PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0030),
.class = PCI_CLASS_MEMORY_RAM << 8, .class_mask = 0xffff00,
.driver_data = (kernel_ulong_t)rcar_barno,
},
{ },
};
+7
View File
@@ -59,6 +59,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>
#include "linux/ntb.h"
#include "linux/ntb_transport.h"
@@ -241,6 +242,9 @@ struct ntb_transport_ctx {
struct work_struct link_cleanup;
struct dentry *debugfs_node_dir;
/* Make sure workq of link event be executed serially */
struct mutex link_event_lock;
};
enum {
@@ -1024,6 +1028,7 @@ static void ntb_transport_link_cleanup_work(struct work_struct *work)
struct ntb_transport_ctx *nt =
container_of(work, struct ntb_transport_ctx, link_cleanup);
guard(mutex)(&nt->link_event_lock);
ntb_transport_link_cleanup(nt);
}
@@ -1047,6 +1052,8 @@ static void ntb_transport_link_work(struct work_struct *work)
u32 val;
int rc = 0, i, spad;
guard(mutex)(&nt->link_event_lock);
/* send the local info, in the opposite order of the way we read it */
if (nt->use_msi) {
+3 -5
View File
@@ -126,9 +126,9 @@ config FB_ACORN
config FB_CLPS711X
tristate "CLPS711X LCD support"
depends on FB && (ARCH_CLPS711X || COMPILE_TEST)
depends on LCD_CLASS_DEVICE
select FB_IOMEM_HELPERS
select FB_MODE_HELPERS
select LCD_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y to enable the Framebuffer driver for the Cirrus Logic
@@ -150,7 +150,7 @@ config FB_IMX
tristate "Freescale i.MX1/21/25/27 LCD support"
depends on FB && HAVE_CLK && HAS_IOMEM
depends on ARCH_MXC || COMPILE_TEST
select LCD_CLASS_DEVICE
depends on LCD_CLASS_DEVICE
select FB_IOMEM_HELPERS
select FB_MODE_HELPERS
select VIDEOMODE_HELPERS
@@ -948,9 +948,6 @@ config FB_RADEON
a framebuffer device. There are both PCI and AGP versions. You
don't need to choose this to run the Radeon in plain VGA mode.
There is a product page at
https://products.amd.com/en-us/GraphicCardResult.aspx
config FB_RADEON_I2C
bool "DDC/I2C for ATI Radeon support"
depends on FB_RADEON
@@ -1060,6 +1057,7 @@ config FB_S3
select FB_TILEBLITTING
select FB_SVGALIB
select VGASTATE
select FB_CFB_REV_PIXELS_IN_BYTE
select FONT_8x16 if FRAMEBUFFER_CONSOLE
help
Driver for graphics boards with S3 Trio / S3 Virge chip.
+17
View File
@@ -160,6 +160,11 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
image.height = vc->vc_font.height;
image.depth = 1;
if (image.dy >= info->var.yres)
return;
image.height = min(image.height, info->var.yres - image.dy);
if (attribute) {
buf = kmalloc(cellsize, GFP_ATOMIC);
if (!buf)
@@ -173,6 +178,18 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
cnt = count;
image.width = vc->vc_font.width * cnt;
if (image.dx >= info->var.xres)
break;
if (image.dx + image.width > info->var.xres) {
image.width = info->var.xres - image.dx;
cnt = image.width / vc->vc_font.width;
if (cnt == 0)
break;
image.width = cnt * vc->vc_font.width;
}
pitch = DIV_ROUND_UP(image.width, 8) + scan_align;
pitch &= ~scan_align;
size = pitch * image.height + buf_align;
+1 -1
View File
@@ -40,7 +40,7 @@ int fb_get_options(const char *name, char **option)
bool enabled;
if (name)
is_of = strncmp(name, "offb", 4);
is_of = !strncmp(name, "offb", 4);
enabled = __video_get_options(name, &options, is_of);
+1 -2
View File
@@ -92,8 +92,7 @@ static unsigned long pixel_to_pat(int bpp, u32 color)
pattern = pattern | pattern << bpp;
break;
default:
pattern = color;
break;
return color;
}
#ifndef __LITTLE_ENDIAN
pattern <<= (BITS_PER_LONG % bpp);
+4 -3
View File
@@ -36,6 +36,7 @@
#include <video/of_videomode.h>
#include <video/videomode.h>
#include "../edid.h"
#include <linux/string_choices.h>
/*
* EDID parser
@@ -320,9 +321,9 @@ static void get_dpms_capabilities(unsigned char flags,
if (flags & DPMS_STANDBY)
specs->dpms |= FB_DPMS_STANDBY;
DPRINTK(" DPMS: Active %s, Suspend %s, Standby %s\n",
(flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
(flags & DPMS_SUSPEND) ? "yes" : "no",
(flags & DPMS_STANDBY) ? "yes" : "no");
str_yes_no(flags & DPMS_ACTIVE_OFF),
str_yes_no(flags & DPMS_SUSPEND),
str_yes_no(flags & DPMS_STANDBY));
}
static void get_chroma(unsigned char *block, struct fb_monspecs *specs)
+1 -1
View File
@@ -674,7 +674,7 @@ static int of_platform_mb862xx_probe(struct platform_device *ofdev)
struct fb_info *info;
struct resource res;
resource_size_t res_size;
unsigned long ret = -ENODEV;
int ret = -ENODEV;
if (of_address_to_resource(np, 0, &res)) {
dev_err(dev, "Invalid address\n");
+2 -1
View File
@@ -22,6 +22,7 @@
#include <linux/pci.h>
#include <linux/console.h>
#include <linux/backlight.h>
#include <linux/string_choices.h>
#ifdef CONFIG_BOOTX_TEXT
#include <asm/btext.h>
#endif
@@ -622,7 +623,7 @@ static int nvidiafb_set_par(struct fb_info *info)
else
par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1);
printk(KERN_INFO PFX "Flat panel dithering %s\n",
par->FPDither ? "enabled" : "disabled");
str_enabled_disabled(par->FPDither));
}
info->fix.visual = (info->var.bits_per_pixel == 8) ?
+2 -1
View File
@@ -60,6 +60,7 @@
#include <linux/soc/pxa/cpu.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
#include <linux/string_choices.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -1419,7 +1420,7 @@ static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
if (ret < 0)
pr_warn("Unable to %s LCD supply regulator: %d\n",
on ? "enable" : "disable", ret);
str_enable_disable(on), ret);
else
fbi->lcd_supply_enabled = on;
}
+123 -54
View File
@@ -50,10 +50,14 @@ struct s3fb_info {
static const struct svga_fb_format s3fb_formats[] = {
{ 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4, FB_VISUAL_PSEUDOCOLOR, 8, 16},
{ 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 0,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 16},
{ 1, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0}, 2,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 32, 64},
{ 2, {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, 2,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 16, 32},
{ 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 1,
FB_TYPE_INTERLEAVED_PLANES, 1, FB_VISUAL_PSEUDOCOLOR, 8, 16},
{ 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 2,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 16},
{ 8, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 4, 8},
{16, {10, 5, 0}, {5, 5, 0}, {0, 5, 0}, {0, 0, 0}, 0,
@@ -557,7 +561,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* 32bpp mode is not supported on VIRGE VX,
24bpp is not supported on others */
if ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6))
if ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 9) : (rv == 8))
rv = -EINVAL;
if (rv < 0) {
@@ -607,7 +611,7 @@ static int s3fb_set_par(struct fb_info *info)
struct s3fb_info *par = info->par;
u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes;
u32 bpp = info->var.bits_per_pixel;
u32 htotal, hsstart;
u32 htotal, hsstart, pel_msk;
if (bpp != 0) {
info->fix.ypanstep = 1;
@@ -617,9 +621,11 @@ static int s3fb_set_par(struct fb_info *info)
info->tileops = NULL;
/* in 4bpp supports 8p wide tiles only, any tiles otherwise */
if (bpp == 4) {
if (bpp == 4 && (info->var.nonstd & 1) != 0) {
int i;
bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
set_bit(8 - 1, info->pixmap.blit_x);
for (i = 8; i <= FB_MAX_BLIT_WIDTH; i += 8)
set_bit(i - 1, info->pixmap.blit_x);
} else {
bitmap_fill(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
}
@@ -730,7 +736,7 @@ static int s3fb_set_par(struct fb_info *info)
vga_wcrt(par->state.vgabase, 0x50, 0x00);
vga_wcrt(par->state.vgabase, 0x67, 0x50);
msleep(10); /* screen remains blank sometimes without this */
vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09);
vga_wcrt(par->state.vgabase, 0x63, (mode <= 4) ? 0x90 : 0x09);
vga_wcrt(par->state.vgabase, 0x66, 0x90);
}
@@ -763,12 +769,17 @@ static int s3fb_set_par(struct fb_info *info)
svga_wcrt_mask(par->state.vgabase, 0x31, 0x00, 0x40);
multiplex = 0;
hmul = 1;
pel_msk = 0xff;
svga_wcrt_mask(par->state.vgabase, 0x08, 0x00, 0x60);
svga_wcrt_mask(par->state.vgabase, 0x05, 0x00, 0x60);
/* Set mode-specific register values */
switch (mode) {
case 0:
fb_dbg(info, "text mode\n");
svga_set_textmode_vga_regs(par->state.vgabase);
pel_msk = 0x0f;
/* Set additional registers like in 8-bit mode */
svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
@@ -783,8 +794,11 @@ static int s3fb_set_par(struct fb_info *info)
}
break;
case 1:
fb_dbg(info, "4 bit pseudocolor\n");
vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
fb_dbg(info, "1 bit pseudocolor\n");
svga_wseq_mask(par->state.vgabase, 0x01, 0x10, 0x14);
svga_wcrt_mask(par->state.vgabase, 0x08, 0x60, 0x60);
svga_wcrt_mask(par->state.vgabase, 0x05, 0x40, 0x60);
pel_msk = 0x01;
/* Set additional registers like in 8-bit mode */
svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
@@ -794,7 +808,13 @@ static int s3fb_set_par(struct fb_info *info)
svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
break;
case 2:
fb_dbg(info, "4 bit pseudocolor, planar\n");
fb_dbg(info, "2 bit pseudocolor\n");
svga_wseq_mask(par->state.vgabase, 0x01, 0x04, 0x14);
svga_wseq_mask(par->state.vgabase, 0x04, 0x08, 0x08);
vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x20);
svga_wcrt_mask(par->state.vgabase, 0x08, 0x20, 0x60);
svga_wcrt_mask(par->state.vgabase, 0x05, 0x40, 0x60);
pel_msk = 0x03;
/* Set additional registers like in 8-bit mode */
svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
@@ -804,8 +824,35 @@ static int s3fb_set_par(struct fb_info *info)
svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
break;
case 3:
fb_dbg(info, "4 bit pseudocolor, planar\n");
pel_msk = 0x0f;
/* Set additional registers like in 8-bit mode */
svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
svga_wcrt_mask(par->state.vgabase, 0x05, 0x40, 0x60);
/* disable enhanced mode */
svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
break;
case 4:
fb_dbg(info, "4 bit pseudocolor\n");
vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
svga_wattr(par->state.vgabase, 0x33, 0x01);
svga_wcrt_mask(par->state.vgabase, 0x05, 0x40, 0x60);
pel_msk = 0xf0;
/* Set additional registers like in 8-bit mode */
svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
/* disable enhanced mode */
svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
break;
case 5:
fb_dbg(info, "8 bit pseudocolor\n");
svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
svga_wcrt_mask(par->state.vgabase, 0x05, 0x20, 0x60);
if (info->var.pixclock > 20000 ||
par->chip == CHIP_357_VIRGE_GX2 ||
par->chip == CHIP_359_VIRGE_GX2P ||
@@ -819,7 +866,7 @@ static int s3fb_set_par(struct fb_info *info)
multiplex = 1;
}
break;
case 4:
case 6:
fb_dbg(info, "5/5/5 truecolor\n");
if (par->chip == CHIP_988_VIRGE_VX) {
if (info->var.pixclock > 20000)
@@ -847,7 +894,7 @@ static int s3fb_set_par(struct fb_info *info)
hmul = 2;
}
break;
case 5:
case 7:
fb_dbg(info, "5/6/5 truecolor\n");
if (par->chip == CHIP_988_VIRGE_VX) {
if (info->var.pixclock > 20000)
@@ -875,12 +922,12 @@ static int s3fb_set_par(struct fb_info *info)
hmul = 2;
}
break;
case 6:
case 8:
/* VIRGE VX case */
fb_dbg(info, "8/8/8 truecolor\n");
svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0);
break;
case 7:
case 9:
fb_dbg(info, "8/8/8/8 truecolor\n");
svga_wcrt_mask(par->state.vgabase, 0x50, 0x30, 0x30);
svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0);
@@ -889,6 +936,7 @@ static int s3fb_set_par(struct fb_info *info)
fb_err(info, "unsupported mode - bug\n");
return -EINVAL;
}
vga_w(par->state.vgabase, VGA_PEL_MSK, pel_msk);
if (par->chip != CHIP_988_VIRGE_VX) {
svga_wseq_mask(par->state.vgabase, 0x15, multiplex ? 0x10 : 0x00, 0x10);
@@ -927,33 +975,26 @@ static int s3fb_set_par(struct fb_info *info)
static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *fb)
{
struct s3fb_info *par = fb->par;
int cols;
switch (fb->var.bits_per_pixel) {
case 0:
case 1:
case 2:
case 4:
if (regno >= 16)
return -EINVAL;
if ((fb->var.bits_per_pixel == 4) &&
(fb->var.nonstd == 0)) {
outb(0xF0, VGA_PEL_MSK);
outb(regno*16, VGA_PEL_IW);
} else {
outb(0x0F, VGA_PEL_MSK);
outb(regno, VGA_PEL_IW);
}
outb(red >> 10, VGA_PEL_D);
outb(green >> 10, VGA_PEL_D);
outb(blue >> 10, VGA_PEL_D);
break;
case 8:
if (regno >= 256)
cols = 1 << (fb->var.bits_per_pixel ? fb->var.bits_per_pixel : 4);
if (regno >= cols)
return -EINVAL;
outb(0xFF, VGA_PEL_MSK);
outb(regno, VGA_PEL_IW);
outb(red >> 10, VGA_PEL_D);
outb(green >> 10, VGA_PEL_D);
outb(blue >> 10, VGA_PEL_D);
if ((fb->var.bits_per_pixel == 4) && ((fb->var.nonstd & 1) == 0))
regno <<= 4;
vga_w(par->state.vgabase, VGA_PEL_IW, regno);
vga_w(par->state.vgabase, VGA_PEL_D, red >> 10);
vga_w(par->state.vgabase, VGA_PEL_D, green >> 10);
vga_w(par->state.vgabase, VGA_PEL_D, blue >> 10);
break;
case 16:
if (regno >= 16)
@@ -988,34 +1029,30 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static int s3fb_blank(int blank_mode, struct fb_info *info)
{
struct s3fb_info *par = info->par;
u8 data;
data = (blank_mode == FB_BLANK_UNBLANK) ? 0x00 : 0x20;
svga_wseq_mask(par->state.vgabase, 0x01, data, 0x20);
svga_wseq_mask(par->state.vgabase, 0x18, data, 0x20);
switch (blank_mode) {
case FB_BLANK_UNBLANK:
fb_dbg(info, "unblank\n");
svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06);
svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
break;
case FB_BLANK_NORMAL:
fb_dbg(info, "blank\n");
svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06);
svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
default:
data = 0x00;
break;
case FB_BLANK_HSYNC_SUSPEND:
fb_dbg(info, "hsync\n");
svga_wcrt_mask(par->state.vgabase, 0x56, 0x02, 0x06);
svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
data = 0x02;
break;
case FB_BLANK_VSYNC_SUSPEND:
fb_dbg(info, "vsync\n");
svga_wcrt_mask(par->state.vgabase, 0x56, 0x04, 0x06);
svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
data = 0x04;
break;
case FB_BLANK_POWERDOWN:
fb_dbg(info, "sync down\n");
svga_wcrt_mask(par->state.vgabase, 0x56, 0x06, 0x06);
svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
data = 0x06;
break;
}
svga_wcrt_mask(par->state.vgabase, 0x56, data, 0x06);
data = (blank_mode == FB_BLANK_POWERDOWN) ? 0x01 : 0x00;
svga_wseq_mask(par->state.vgabase, 0x14, data, 0x01);
return 0;
}
@@ -1045,6 +1082,33 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
return 0;
}
/* Get capabilities of accelerator based on the mode */
static void s3fb_get_caps(struct fb_info *info, struct fb_blit_caps *caps,
struct fb_var_screeninfo *var)
{
int i;
if (var->bits_per_pixel == 0) {
/* can only support 256 8x16 bitmap */
bitmap_zero(caps->x, FB_MAX_BLIT_WIDTH);
set_bit(8 - 1, caps->x);
bitmap_zero(caps->y, FB_MAX_BLIT_HEIGHT);
set_bit(16 - 1, caps->y);
caps->len = 256;
} else {
if (var->bits_per_pixel == 4 && (var->nonstd & 1) != 0) {
bitmap_zero(caps->x, FB_MAX_BLIT_WIDTH);
for (i = 8; i <= FB_MAX_BLIT_WIDTH; i += 8)
set_bit(i - 1, caps->x);
} else {
bitmap_fill(caps->x, FB_MAX_BLIT_WIDTH);
}
bitmap_fill(caps->y, FB_MAX_BLIT_HEIGHT);
caps->len = ~(u32)0;
}
}
/* ------------------------------------------------------------------------- */
/* Frame buffer operations */
@@ -1063,7 +1127,7 @@ static const struct fb_ops s3fb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = s3fb_imageblit,
__FB_DEFAULT_IOMEM_OPS_MMAP,
.fb_get_caps = svga_get_caps,
.fb_get_caps = s3fb_get_caps,
};
/* ------------------------------------------------------------------------- */
@@ -1445,6 +1509,8 @@ static int __maybe_unused s3_pci_suspend(struct device *dev)
}
fb_set_suspend(info, 1);
svga_wseq_mask(par->state.vgabase, 0x18, 0x20, 0x20);
svga_wseq_mask(par->state.vgabase, 0x14, 0x01, 0x01);
mutex_unlock(&(par->open_lock));
console_unlock();
@@ -1471,6 +1537,9 @@ static int __maybe_unused s3_pci_resume(struct device *dev)
return 0;
}
vga_wseq(par->state.vgabase, 0x08, 0x06);
svga_wseq_mask(par->state.vgabase, 0x18, 0x00, 0x20);
svga_wseq_mask(par->state.vgabase, 0x14, 0x00, 0x01);
s3fb_set_par(info);
fb_set_suspend(info, 0);
+23 -8
View File
@@ -93,6 +93,7 @@ struct simplefb_par {
static void simplefb_clocks_destroy(struct simplefb_par *par);
static void simplefb_regulators_destroy(struct simplefb_par *par);
static void simplefb_detach_genpds(void *res);
/*
* fb_ops.fb_destroy is called by the last put_fb_info() call at the end
@@ -105,6 +106,7 @@ static void simplefb_destroy(struct fb_info *info)
simplefb_regulators_destroy(info->par);
simplefb_clocks_destroy(info->par);
simplefb_detach_genpds(info->par);
if (info->screen_base)
iounmap(info->screen_base);
@@ -445,13 +447,14 @@ static void simplefb_detach_genpds(void *res)
if (!IS_ERR_OR_NULL(par->genpds[i]))
dev_pm_domain_detach(par->genpds[i], true);
}
par->num_genpds = 0;
}
static int simplefb_attach_genpds(struct simplefb_par *par,
struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
unsigned int i;
unsigned int i, num_genpds;
int err;
err = of_count_phandle_with_args(dev->of_node, "power-domains",
@@ -465,26 +468,35 @@ static int simplefb_attach_genpds(struct simplefb_par *par,
return err;
}
par->num_genpds = err;
num_genpds = err;
/*
* Single power-domain devices are handled by the driver core, so
* nothing to do here.
*/
if (par->num_genpds <= 1)
if (num_genpds <= 1) {
par->num_genpds = num_genpds;
return 0;
}
par->genpds = devm_kcalloc(dev, par->num_genpds, sizeof(*par->genpds),
par->genpds = devm_kcalloc(dev, num_genpds, sizeof(*par->genpds),
GFP_KERNEL);
if (!par->genpds)
return -ENOMEM;
par->genpd_links = devm_kcalloc(dev, par->num_genpds,
par->genpd_links = devm_kcalloc(dev, num_genpds,
sizeof(*par->genpd_links),
GFP_KERNEL);
if (!par->genpd_links)
return -ENOMEM;
/*
* Set par->num_genpds only after genpds and genpd_links are allocated
* to exit early from simplefb_detach_genpds() without full
* initialisation.
*/
par->num_genpds = num_genpds;
for (i = 0; i < par->num_genpds; i++) {
par->genpds[i] = dev_pm_domain_attach_by_id(dev, i);
if (IS_ERR(par->genpds[i])) {
@@ -506,9 +518,10 @@ static int simplefb_attach_genpds(struct simplefb_par *par,
dev_warn(dev, "failed to link power-domain %u\n", i);
}
return devm_add_action_or_reset(dev, simplefb_detach_genpds, par);
return 0;
}
#else
static void simplefb_detach_genpds(void *res) { }
static int simplefb_attach_genpds(struct simplefb_par *par,
struct platform_device *pdev)
{
@@ -622,18 +635,20 @@ static int simplefb_probe(struct platform_device *pdev)
ret = devm_aperture_acquire_for_platform_device(pdev, par->base, par->size);
if (ret) {
dev_err(&pdev->dev, "Unable to acquire aperture: %d\n", ret);
goto error_regulators;
goto error_genpds;
}
ret = register_framebuffer(info);
if (ret < 0) {
dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
goto error_regulators;
goto error_genpds;
}
dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
return 0;
error_genpds:
simplefb_detach_genpds(par);
error_regulators:
simplefb_regulators_destroy(par);
error_clocks:
+1 -1
View File
@@ -390,7 +390,7 @@ static int xenfb_probe(struct xenbus_device *dev,
info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
info->gfns = vmalloc(array_size(sizeof(unsigned long), info->nr_pages));
info->gfns = vmalloc_array(info->nr_pages, sizeof(unsigned long));
if (!info->gfns)
goto error_nomem;
+2 -1
View File
@@ -433,7 +433,8 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
bio->bi_private = dio;
bio->bi_end_io = iomap_dio_bio_end_io;
ret = bio_iov_iter_get_bdev_pages(bio, dio->submit.iter, iomap->bdev);
ret = bio_iov_iter_get_pages(bio, dio->submit.iter,
bdev_logical_block_size(iomap->bdev) - 1);
if (unlikely(ret)) {
/*
* We have to stop part way through an IO. We must fall
+1 -6
View File
@@ -446,14 +446,9 @@ int submit_bio_wait(struct bio *bio);
int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data,
size_t len, enum req_op op);
int bio_iov_iter_get_pages_aligned(struct bio *bio, struct iov_iter *iter,
int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
unsigned len_align_mask);
static inline int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
{
return bio_iov_iter_get_pages_aligned(bio, iter, 0);
}
void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter);
void __bio_release_pages(struct bio *bio, bool mark_dirty);
extern void bio_set_pages_dirty(struct bio *bio);
-7
View File
@@ -1873,13 +1873,6 @@ static inline int bio_split_rw_at(struct bio *bio,
return bio_split_io_at(bio, lim, segs, max_bytes, lim->dma_alignment);
}
static inline int bio_iov_iter_get_bdev_pages(struct bio *bio,
struct iov_iter *iter, struct block_device *bdev)
{
return bio_iov_iter_get_pages_aligned(bio, iter,
bdev_logical_block_size(bdev) - 1);
}
#define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
#endif /* _LINUX_BLKDEV_H */
+1 -1
View File
@@ -71,7 +71,7 @@ struct i2c_algo_pca_data {
void *data; /* private low level data */
void (*write_byte) (void *data, int reg, int val);
int (*read_byte) (void *data, int reg);
int (*wait_for_completion) (void *data);
int (*wait_for_completion_cb) (void *data);
void (*reset_chip) (void *data);
/* For PCA9564, use one of the predefined frequencies:
* 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000
+2 -2
View File
@@ -17,8 +17,8 @@ struct disk_stats {
/*
* Macros to operate on percpu disk statistics:
*
* {disk|part|all}_stat_{add|sub|inc|dec}() modify the stat counters and should
* be called between disk_stat_lock() and disk_stat_unlock().
* part_stat_{add|sub|inc|dec}() modify the stat counters and should
* be called between part_stat_lock() and part_stat_unlock().
*
* part_stat_read() can be called at any time.
*/
+3 -2
View File
@@ -228,10 +228,11 @@ enum tpm2_timeouts {
TPM2_TIMEOUT_B = 4000,
TPM2_TIMEOUT_C = 200,
TPM2_TIMEOUT_D = 30,
};
enum tpm2_durations {
TPM2_DURATION_SHORT = 20,
TPM2_DURATION_MEDIUM = 750,
TPM2_DURATION_LONG = 2000,
TPM2_DURATION_LONG_LONG = 300000,
TPM2_DURATION_DEFAULT = 120000,
};
+1 -1
View File
@@ -404,7 +404,7 @@ enum io_uring_op {
* will be contiguous from the starting buffer ID.
*
* IORING_SEND_VECTORIZED If set, SEND[_ZC] will take a pointer to a io_vec
* to allow vectorized send operations.
* to allow vectorized send operations.
*/
#define IORING_RECVSEND_POLL_FIRST (1U << 0)
#define IORING_RECV_MULTISHOT (1U << 1)
+1 -1
View File
@@ -29,7 +29,7 @@
*
* Also see the examples in the liburing library:
*
* git://git.kernel.dk/liburing
* git://git.kernel.org/pub/scm/linux/kernel/git/axboe/liburing.git
*
* io_uring also uses READ/WRITE_ONCE() for _any_ store or load that happens
* from data shared between the kernel and application. This is done both
+2 -1
View File
@@ -230,13 +230,14 @@ static int io_waitid_wait(struct wait_queue_entry *wait, unsigned mode,
if (!pid_child_should_wake(wo, p))
return 0;
list_del_init(&wait->entry);
/* cancel is in progress */
if (atomic_fetch_inc(&iw->refs) & IO_WAITID_REF_MASK)
return 1;
req->io_task_work.func = io_waitid_cb;
io_req_task_work_add(req);
list_del_init(&wait->entry);
return 1;
}
+5
View File
@@ -1079,6 +1079,7 @@ static ssize_t io_copy_page(struct io_copy_cache *cc, struct page *src_page,
cc->size -= n;
cc->offset += n;
src_offset += n;
len -= n;
copied += n;
}
@@ -1236,12 +1237,16 @@ io_zcrx_recv_skb(read_descriptor_t *desc, struct sk_buff *skb,
end = start + frag_iter->len;
if (offset < end) {
size_t count;
copy = end - offset;
if (copy > len)
copy = len;
off = offset - start;
count = desc->count;
ret = io_zcrx_recv_skb(desc, frag_iter, off, copy);
desc->count = count;
if (ret < 0)
goto out;
+1
View File
@@ -1549,6 +1549,7 @@ static const struct snd_pci_quirk force_connect_list[] = {
SND_PCI_QUIRK(0x103c, 0x83e2, "HP EliteDesk 800 G4", 1),
SND_PCI_QUIRK(0x103c, 0x83ef, "HP MP9 G4 Retail System AMS", 1),
SND_PCI_QUIRK(0x103c, 0x845a, "HP EliteDesk 800 G4 DM 65W", 1),
SND_PCI_QUIRK(0x103c, 0x83f3, "HP ProDesk 400", 1),
SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1),
SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
+10
View File
@@ -3735,6 +3735,7 @@ enum {
ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC,
ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1,
ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC,
ALC289_FIXUP_ASUS_ZEPHYRUS_DUAL_SPK,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -6164,6 +6165,14 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE,
},
[ALC289_FIXUP_ASUS_ZEPHYRUS_DUAL_SPK] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x17, 0x90170151 }, /* Internal Speaker LFE */
{ 0x1e, 0x90170150 }, /* Internal Speaker */
{ }
},
}
};
static const struct hda_quirk alc269_fixup_tbl[] = {
@@ -6718,6 +6727,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1573, "ASUS GZ301VV/VQ/VU/VJ/VA/VC/VE/VVC/VQC/VUC/VJC/VEC/VCC", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1652, "ASUS ROG Zephyrus Do 15 SE", ALC289_FIXUP_ASUS_ZEPHYRUS_DUAL_SPK),
SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZI/ZJ/ZQ/ZU/ZV", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2),
@@ -474,6 +474,12 @@ static void tasdevice_dspfw_init(void *context)
if (tas_priv->fmw->nr_configurations > 0)
tas_priv->cur_conf = 0;
/* Init common setting for different audio profiles */
if (tas_priv->rcabin.init_profile_id >= 0)
tasdevice_select_cfg_blk(tas_priv,
tas_priv->rcabin.init_profile_id,
TASDEVICE_BIN_BLK_PRE_POWER_UP);
/* If calibrated data occurs error, dsp will still works with default
* calibrated data inside algo.
*/
@@ -770,6 +776,12 @@ static int tas2781_system_resume(struct device *dev)
tasdevice_reset(tas_hda->priv);
tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
/* Init common setting for different audio profiles */
if (tas_hda->priv->rcabin.init_profile_id >= 0)
tasdevice_select_cfg_blk(tas_hda->priv,
tas_hda->priv->rcabin.init_profile_id,
TASDEVICE_BIN_BLK_PRE_POWER_UP);
if (tas_hda->priv->playback_started)
tasdevice_tuning_switch(tas_hda->priv, 0);
+1 -1
View File
@@ -21,7 +21,7 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg)
switch (reg) {
case 0x2f01 ... 0x2f0a:
case 0x2f35 ... 0x2f36:
case 0x2f50:
case 0x2f50 ... 0x2f52:
case 0x2f54:
case 0x2f58 ... 0x2f5d:
case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0):
+14
View File
@@ -1378,6 +1378,9 @@ static void rt722_sdca_dmic_preset(struct rt722_sdca_priv *rt722)
/* PHYtiming TDZ/TZD control */
regmap_write(rt722->regmap, 0x2f03, 0x06);
if (rt722->hw_vid == RT722_VB)
regmap_write(rt722->regmap, 0x2f52, 0x00);
/* clear flag */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0),
@@ -1415,6 +1418,9 @@ static void rt722_sdca_amp_preset(struct rt722_sdca_priv *rt722)
SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23,
RT722_SDCA_CTL_VENDOR_DEF, CH_08), 0x04);
if (rt722->hw_vid == RT722_VB)
regmap_write(rt722->regmap, 0x2f54, 0x00);
/* clear flag */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0),
@@ -1506,6 +1512,9 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
0x0010);
if (rt722->hw_vid == RT722_VB)
regmap_write(rt722->regmap, 0x2f51, 0x00);
/* clear flag */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0),
@@ -1516,6 +1525,7 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave)
{
struct rt722_sdca_priv *rt722 = dev_get_drvdata(dev);
unsigned int val;
rt722->disable_irq = false;
@@ -1545,6 +1555,10 @@ int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave)
pm_runtime_get_noresume(&slave->dev);
rt722_sdca_index_read(rt722, RT722_VENDOR_REG, RT722_JD_PRODUCT_NUM, &val);
rt722->hw_vid = (val & 0x0f00) >> 8;
dev_dbg(&slave->dev, "%s hw_vid=0x%x\n", __func__, rt722->hw_vid);
rt722_sdca_dmic_preset(rt722);
rt722_sdca_amp_preset(rt722);
rt722_sdca_jack_preset(rt722);
+6
View File
@@ -39,6 +39,7 @@ struct rt722_sdca_priv {
/* For DMIC */
bool fu1e_dapm_mute;
bool fu1e_mixer_mute[4];
int hw_vid;
};
struct rt722_sdca_dmic_kctrl_priv {
@@ -233,6 +234,11 @@ enum rt722_sdca_jd_src {
RT722_JD1,
};
enum rt722_sdca_version {
RT722_VA,
RT722_VB,
};
int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave);
int rt722_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave *slave);
int rt722_sdca_index_write(struct rt722_sdca_priv *rt722,
+6 -3
View File
@@ -236,8 +236,12 @@ static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
inv == SND_SOC_DAIFMT_IB_IF)
val |= AIU_CLK_CTRL_LRCLK_INVERT;
if (inv == SND_SOC_DAIFMT_IB_NF ||
inv == SND_SOC_DAIFMT_IB_IF)
/*
* The SoC changes data on the rising edge of the bitclock
* so an inversion of the bitclock is required in normal mode
*/
if (inv == SND_SOC_DAIFMT_NB_NF ||
inv == SND_SOC_DAIFMT_NB_IF)
val |= AIU_CLK_CTRL_AOCLK_INVERT;
/* Signal skew */
@@ -328,4 +332,3 @@ const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = {
.startup = aiu_encoder_i2s_startup,
.shutdown = aiu_encoder_i2s_shutdown,
};
+21 -8
View File
@@ -29,6 +29,8 @@
#define SDnFMT_BITS(x) ((x) << 4)
#define SDnFMT_CHAN(x) ((x) << 0)
#define HDA_MAX_PERIOD_TIME_HEADROOM 10
static bool hda_always_enable_dmi_l1;
module_param_named(always_enable_dmi_l1, hda_always_enable_dmi_l1, bool, 0444);
MODULE_PARM_DESC(always_enable_dmi_l1, "SOF HDA always enable DMI l1");
@@ -291,19 +293,30 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
* On playback start the DMA will transfer dsp_max_burst_size_in_ms
* amount of data in one initial burst to fill up the host DMA buffer.
* Consequent DMA burst sizes are shorter and their length can vary.
* To make sure that userspace allocate large enough ALSA buffer we need
* to place a constraint on the buffer time.
* To avoid immediate xrun by the initial burst we need to place
* constraint on the period size (via PERIOD_TIME) to cover the size of
* the host buffer.
* We need to add headroom of max 10ms as the firmware needs time to
* settle to the 1ms pacing and initially it can run faster for few
* internal periods.
*
* On capture the DMA will transfer 1ms chunks.
*
* Exact dsp_max_burst_size_in_ms constraint is racy, so set the
* constraint to a minimum of 2x dsp_max_burst_size_in_ms.
*/
if (spcm->stream[direction].dsp_max_burst_size_in_ms)
if (spcm->stream[direction].dsp_max_burst_size_in_ms) {
unsigned int period_time = spcm->stream[direction].dsp_max_burst_size_in_ms;
/*
* add headroom over the maximum burst size to cover the time
* needed for the DMA pace to settle.
* Limit the headroom time to HDA_MAX_PERIOD_TIME_HEADROOM
*/
period_time += min(period_time, HDA_MAX_PERIOD_TIME_HEADROOM);
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_BUFFER_TIME,
spcm->stream[direction].dsp_max_burst_size_in_ms * USEC_PER_MSEC * 2,
SNDRV_PCM_HW_PARAM_PERIOD_TIME,
period_time * USEC_PER_MSEC,
UINT_MAX);
}
/* binding pcm substream to hda stream */
substream->runtime->private_data = &dsp_stream->hstream;
+27 -2
View File
@@ -1129,10 +1129,35 @@ u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct hdac_stream *hstream = substream->runtime->private_data;
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_pcm_runtime *be_rtd = NULL;
struct hdac_ext_stream *hext_stream;
struct snd_soc_dai *cpu_dai;
struct snd_soc_dpcm *dpcm;
u32 llp_l, llp_u;
/*
* The LLP needs to be read from the Link DMA used for this FE as it is
* allowed to use any combination of Link and Host channels
*/
for_each_dpcm_be(rtd, substream->stream, dpcm) {
if (dpcm->fe != rtd)
continue;
be_rtd = dpcm->be;
}
if (!be_rtd)
return 0;
cpu_dai = snd_soc_rtd_to_cpu(be_rtd, 0);
if (!cpu_dai)
return 0;
hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
if (!hext_stream)
return 0;
/*
* The pplc_addr have been calculated during probe in
* hda_dsp_stream_init():
+5 -5
View File
@@ -2473,11 +2473,6 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif
if (ret < 0)
return ret;
/* free all the scheduler widgets now */
ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify);
if (ret < 0)
return ret;
/*
* Tear down all pipelines associated with PCMs that did not get suspended
* and unset the prepare flag so that they can be set up again during resume.
@@ -2493,6 +2488,11 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif
}
}
/* free all the scheduler widgets now. This will also power down the secondary cores */
ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify);
if (ret < 0)
return ret;
list_for_each_entry(sroute, &sdev->route_list, list)
sroute->setup = false;
+80 -24
View File
@@ -19,12 +19,14 @@
* struct sof_ipc4_timestamp_info - IPC4 timestamp info
* @host_copier: the host copier of the pcm stream
* @dai_copier: the dai copier of the pcm stream
* @stream_start_offset: reported by fw in memory window (converted to frames)
* @stream_end_offset: reported by fw in memory window (converted to frames)
* @stream_start_offset: reported by fw in memory window (converted to
* frames at host_copier sampling rate)
* @stream_end_offset: reported by fw in memory window (converted to
* frames at host_copier sampling rate)
* @llp_offset: llp offset in memory window
* @boundary: wrap boundary should be used for the LLP frame counter
* @delay: Calculated and stored in pointer callback. The stored value is
* returned in the delay callback.
* returned in the delay callback. Expressed in frames at host copier
* sampling rate.
*/
struct sof_ipc4_timestamp_info {
struct sof_ipc4_copier *host_copier;
@@ -33,7 +35,6 @@ struct sof_ipc4_timestamp_info {
u64 stream_end_offset;
u32 llp_offset;
u64 boundary;
snd_pcm_sframes_t delay;
};
@@ -48,6 +49,18 @@ struct sof_ipc4_pcm_stream_priv {
bool chain_dma_allocated;
};
/*
* Modulus to use to compare host and link position counters. The sampling
* rates may be different, so the raw hardware counters will wrap
* around at different times. To calculate differences, use
* DELAY_BOUNDARY as a common modulus. This value must be smaller than
* the wrap-around point of any hardware counter, and larger than any
* valid delay measurement.
*/
#define DELAY_BOUNDARY U32_MAX
#define DELAY_MAX (DELAY_BOUNDARY >> 1)
static inline struct sof_ipc4_timestamp_info *
sof_ipc4_sps_to_time_info(struct snd_sof_pcm_stream *sps)
{
@@ -1049,6 +1062,35 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
return 0;
}
static u64 sof_ipc4_frames_dai_to_host(struct sof_ipc4_timestamp_info *time_info, u64 value)
{
u64 dai_rate, host_rate;
if (!time_info->dai_copier || !time_info->host_copier)
return value;
/*
* copiers do not change sampling rate, so we can use the
* out_format independently of stream direction
*/
dai_rate = time_info->dai_copier->data.out_format.sampling_frequency;
host_rate = time_info->host_copier->data.out_format.sampling_frequency;
if (!dai_rate || !host_rate || dai_rate == host_rate)
return value;
/* take care not to overflow u64, rates can be up to 768000 */
if (value > U32_MAX) {
value = div64_u64(value, dai_rate);
value *= host_rate;
} else {
value *= host_rate;
value = div64_u64(value, dai_rate);
}
return value;
}
static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
struct snd_sof_pcm_stream *sps,
@@ -1068,7 +1110,7 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
return -EINVAL;
} else if (host_copier->data.gtw_cfg.node_id == SOF_IPC4_CHAIN_DMA_NODE_ID) {
/*
* While the firmware does not supports time_info reporting for
* While the firmware does not support time_info reporting for
* streams using ChainDMA, it is granted that ChainDMA can only
* be used on Host+Link pairs where the link position is
* accessible from the host side.
@@ -1076,10 +1118,16 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
* Enable delay calculation in case of ChainDMA via host
* accessible registers.
*
* The ChainDMA uses 2x 1ms ping-pong buffer, dai side starts
* when 1ms data is available
* The ChainDMA prefills the link DMA with a preamble
* of zero samples. Set the stream start offset based
* on size of the preamble (driver provided fifo size
* multiplied by 2.5). We add 1ms of margin as the FW
* will align the buffer size to DMA hardware
* alignment that is not known to host.
*/
time_info->stream_start_offset = substream->runtime->rate / MSEC_PER_SEC;
int pre_ms = SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS * 5 / 2 + 1;
time_info->stream_start_offset = pre_ms * substream->runtime->rate / MSEC_PER_SEC;
goto out;
}
@@ -1099,14 +1147,13 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
time_info->stream_end_offset = ppl_reg.stream_end_offset;
do_div(time_info->stream_end_offset, dai_sample_size);
/* convert to host frame time */
time_info->stream_start_offset =
sof_ipc4_frames_dai_to_host(time_info, time_info->stream_start_offset);
time_info->stream_end_offset =
sof_ipc4_frames_dai_to_host(time_info, time_info->stream_end_offset);
out:
/*
* Calculate the wrap boundary need to be used for delay calculation
* The host counter is in bytes, it will wrap earlier than the frames
* based link counter.
*/
time_info->boundary = div64_u64(~((u64)0),
frames_to_bytes(substream->runtime, 1));
/* Initialize the delay value to 0 (no delay) */
time_info->delay = 0;
@@ -1149,6 +1196,8 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
/* For delay calculation we need the host counter */
host_cnt = snd_sof_pcm_get_host_byte_counter(sdev, component, substream);
/* Store the original value to host_ptr */
host_ptr = host_cnt;
/* convert the host_cnt to frames */
@@ -1167,6 +1216,8 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
sof_mailbox_read(sdev, time_info->llp_offset, &llp, sizeof(llp));
dai_cnt = ((u64)llp.reading.llp_u << 32) | llp.reading.llp_l;
}
dai_cnt = sof_ipc4_frames_dai_to_host(time_info, dai_cnt);
dai_cnt += time_info->stream_end_offset;
/* In two cases dai dma counter is not accurate
@@ -1200,8 +1251,9 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
dai_cnt -= time_info->stream_start_offset;
}
/* Wrap the dai counter at the boundary where the host counter wraps */
div64_u64_rem(dai_cnt, time_info->boundary, &dai_cnt);
/* Convert to a common base before comparisons */
dai_cnt &= DELAY_BOUNDARY;
host_cnt &= DELAY_BOUNDARY;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
head_cnt = host_cnt;
@@ -1211,14 +1263,18 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
tail_cnt = host_cnt;
}
if (head_cnt < tail_cnt) {
time_info->delay = time_info->boundary - tail_cnt + head_cnt;
goto out;
if (unlikely(head_cnt < tail_cnt))
time_info->delay = DELAY_BOUNDARY - tail_cnt + head_cnt;
else
time_info->delay = head_cnt - tail_cnt;
if (time_info->delay > DELAY_MAX) {
spcm_dbg_ratelimited(spcm, substream->stream,
"inaccurate delay, host %llu dai_cnt %llu",
host_cnt, dai_cnt);
time_info->delay = 0;
}
time_info->delay = head_cnt - tail_cnt;
out:
/*
* Convert the host byte counter to PCM pointer which wraps in buffer
* and it is in frames
+7 -3
View File
@@ -33,7 +33,6 @@ MODULE_PARM_DESC(ipc4_ignore_cpc,
#define SOF_IPC4_GAIN_PARAM_ID 0
#define SOF_IPC4_TPLG_ABI_SIZE 6
#define SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS 2
static DEFINE_IDA(alh_group_ida);
static DEFINE_IDA(pipeline_ida);
@@ -666,8 +665,13 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
swidget->tuples,
swidget->num_tuples, sizeof(u32), 1);
/* Set default DMA buffer size if it is not specified in topology */
if (!sps->dsp_max_burst_size_in_ms)
sps->dsp_max_burst_size_in_ms = SOF_IPC4_MIN_DMA_BUFFER_SIZE;
if (!sps->dsp_max_burst_size_in_ms) {
struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
sps->dsp_max_burst_size_in_ms = pipeline->use_chain_dma ?
SOF_IPC4_CHAIN_DMA_BUFFER_SIZE : SOF_IPC4_MIN_DMA_BUFFER_SIZE;
}
} else {
/* Capture data is copied from DSP to host in 1ms bursts */
spcm->stream[dir].dsp_max_burst_size_in_ms = 1;
+7 -2
View File
@@ -70,8 +70,11 @@
#define SOF_IPC4_CHAIN_DMA_NODE_ID 0x7fffffff
#define SOF_IPC4_INVALID_NODE_ID 0xffffffff
/* FW requires minimum 2ms DMA buffer size */
#define SOF_IPC4_MIN_DMA_BUFFER_SIZE 2
/* FW requires minimum 4ms DMA buffer size */
#define SOF_IPC4_MIN_DMA_BUFFER_SIZE 4
/* ChainDMA in fw uses 5ms DMA buffer */
#define SOF_IPC4_CHAIN_DMA_BUFFER_SIZE 5
/*
* The base of multi-gateways. Multi-gateways addressing starts from
@@ -263,6 +266,8 @@ struct sof_ipc4_dma_stream_ch_map {
#define SOF_IPC4_DMA_METHOD_HDA 1
#define SOF_IPC4_DMA_METHOD_GPDMA 2 /* defined for consistency but not used */
#define SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS 2
/**
* struct sof_ipc4_dma_config: DMA configuration
* @dma_method: HDAudio or GPDMA
+5
View File
@@ -629,6 +629,11 @@ void snd_sof_pcm_init_elapsed_work(struct work_struct *work);
(__spcm)->pcm.pcm_id, (__spcm)->pcm.pcm_name, __dir, \
##__VA_ARGS__)
#define spcm_dbg_ratelimited(__spcm, __dir, __fmt, ...) \
dev_dbg_ratelimited((__spcm)->scomp->dev, "pcm%u (%s), dir %d: " __fmt, \
(__spcm)->pcm.pcm_id, (__spcm)->pcm.pcm_name, __dir, \
##__VA_ARGS__)
#define spcm_err(__spcm, __dir, __fmt, ...) \
dev_err((__spcm)->scomp->dev, "%s: pcm%u (%s), dir %d: " __fmt, \
__func__, (__spcm)->pcm.pcm_id, (__spcm)->pcm.pcm_name, __dir, \
+3 -6
View File
@@ -641,12 +641,9 @@ static int fcp_ioctl_set_meter_map(struct usb_mixer_interface *mixer,
return -EINVAL;
/* Allocate and copy the map data */
tmp_map = kmalloc_array(map.map_size, sizeof(s16), GFP_KERNEL);
if (!tmp_map)
return -ENOMEM;
if (copy_from_user(tmp_map, arg->map, map.map_size * sizeof(s16)))
return -EFAULT;
tmp_map = memdup_array_user(arg->map, map.map_size, sizeof(s16));
if (IS_ERR(tmp_map))
return PTR_ERR(tmp_map);
err = validate_meter_map(tmp_map, map.map_size, map.meter_slots);
if (err < 0)