Merge branch 'perf/urgent' into perf/core, to pick up fixes

Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2017-10-27 10:31:44 +02:00
commit 6856b8e536
260 changed files with 3029 additions and 1371 deletions

View file

@ -14,3 +14,11 @@ Description:
Show or set the gain boost of the amp, from 0-31 range.
18 = indoors (default)
14 = outdoors
What /sys/bus/iio/devices/iio:deviceX/noise_level_tripped
Date: May 2017
KernelVersion: 4.13
Contact: Matt Ranostay <matt.ranostay@konsulko.com>
Description:
When 1 the noise level is over the trip level and not reporting
valid data

View file

@ -16,6 +16,10 @@ Optional properties:
- ams,tuning-capacitor-pf: Calibration tuning capacitor stepping
value 0 - 120pF. This will require using the calibration data from
the manufacturer.
- ams,nflwdth: Set the noise and watchdog threshold register on
startup. This will need to set according to the noise from the
MCU board, and possibly the local environment. Refer to the
datasheet for the threshold settings.
Example:
@ -27,4 +31,5 @@ as3935@0 {
interrupt-parent = <&gpio1>;
interrupts = <16 1>;
ams,tuning-capacitor-pf = <80>;
ams,nflwdth = <0x44>;
};

View file

@ -99,7 +99,7 @@ Examples:
compatible = "arm,gic-v3-its";
msi-controller;
#msi-cells = <1>;
reg = <0x0 0x2c200000 0 0x200000>;
reg = <0x0 0x2c200000 0 0x20000>;
};
};
@ -124,14 +124,14 @@ Examples:
compatible = "arm,gic-v3-its";
msi-controller;
#msi-cells = <1>;
reg = <0x0 0x2c200000 0 0x200000>;
reg = <0x0 0x2c200000 0 0x20000>;
};
gic-its@2c400000 {
compatible = "arm,gic-v3-its";
msi-controller;
#msi-cells = <1>;
reg = <0x0 0x2c400000 0 0x200000>;
reg = <0x0 0x2c400000 0 0x20000>;
};
ppi-partitions {

View file

@ -9213,7 +9213,6 @@ F: include/linux/isicom.h
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
M: Bin Liu <b-liu@ti.com>
L: linux-usb@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/musb/

View file

@ -1,7 +1,7 @@
VERSION = 4
PATCHLEVEL = 14
SUBLEVEL = 0
EXTRAVERSION = -rc5
EXTRAVERSION = -rc6
NAME = Fearless Coyote
# *DOCUMENTATION*

View file

@ -131,7 +131,7 @@ endif
KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
CHECKFLAGS += -D__arm__
CHECKFLAGS += -D__arm__ -m32
#Default value
head-y := arch/arm/kernel/head$(MMUEXT).o

View file

@ -23,7 +23,11 @@ ENTRY(putc)
strb r0, [r1]
mov r0, #0x03 @ SYS_WRITEC
ARM( svc #0x123456 )
#ifdef CONFIG_CPU_V7M
THUMB( bkpt #0xab )
#else
THUMB( svc #0xab )
#endif
mov pc, lr
.align 2
1: .word _GLOBAL_OFFSET_TABLE_ - .

View file

@ -178,7 +178,7 @@ gic: interrupt-controller@d000 {
};
i2c0: i2c@11000 {
compatible = "marvell,mv64xxx-i2c";
compatible = "marvell,mv78230-a0-i2c", "marvell,mv64xxx-i2c";
reg = <0x11000 0x20>;
#address-cells = <1>;
#size-cells = <0>;
@ -189,7 +189,7 @@ i2c0: i2c@11000 {
};
i2c1: i2c@11100 {
compatible = "marvell,mv64xxx-i2c";
compatible = "marvell,mv78230-a0-i2c", "marvell,mv64xxx-i2c";
reg = <0x11100 0x20>;
#address-cells = <1>;
#size-cells = <0>;

View file

@ -67,8 +67,8 @@ macb0: ethernet@f8008000 {
pinctrl-0 = <&pinctrl_macb0_default>;
phy-mode = "rmii";
ethernet-phy@1 {
reg = <0x1>;
ethernet-phy@0 {
reg = <0x0>;
interrupt-parent = <&pioA>;
interrupts = <PIN_PD31 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";

View file

@ -309,7 +309,7 @@ adc: adc@fc030000 {
vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_adc_default>;
pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
status = "okay";
};
@ -340,6 +340,20 @@ pinctrl_can1_default: can1_default {
bias-disable;
};
/*
* The ADTRG pin can work on any edge type.
* In here it's being pulled up, so need to
* connect it to ground to get an edge e.g.
* Trigger can be configured on falling, rise
* or any edge, and the pull-up can be changed
* to pull-down or left floating according to
* needs.
*/
pinctrl_adtrg_default: adtrg_default {
pinmux = <PIN_PD31__ADTRG>;
bias-pull-up;
};
pinctrl_charger_chglev: charger_chglev {
pinmux = <PIN_PA12__GPIO>;
bias-disable;

View file

@ -18,12 +18,9 @@ / {
compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
model = "Raspberry Pi Zero W";
/* Needed by firmware to properly init UARTs */
aliases {
uart0 = "/soc/serial@7e201000";
uart1 = "/soc/serial@7e215040";
serial0 = "/soc/serial@7e201000";
serial1 = "/soc/serial@7e215040";
chosen {
/* 8250 auxiliary UART instead of pl011 */
stdout-path = "serial1:115200n8";
};
leds {

View file

@ -8,6 +8,11 @@ / {
compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
model = "Raspberry Pi 3 Model B";
chosen {
/* 8250 auxiliary UART instead of pl011 */
stdout-path = "serial1:115200n8";
};
memory {
reg = <0 0x40000000>;
};

View file

@ -20,8 +20,13 @@ / {
#address-cells = <1>;
#size-cells = <1>;
aliases {
serial0 = &uart0;
serial1 = &uart1;
};
chosen {
bootargs = "earlyprintk console=ttyAMA0";
stdout-path = "serial0:115200n8";
};
thermal-zones {

View file

@ -145,11 +145,12 @@ mux1 {
};
watchdog@41000000 {
compatible = "cortina,gemini-watchdog";
compatible = "cortina,gemini-watchdog", "faraday,ftwdt010";
reg = <0x41000000 0x1000>;
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
resets = <&syscon GEMINI_RESET_WDOG>;
clocks = <&syscon GEMINI_CLK_APB>;
clock-names = "PCLK";
};
uart0: serial@42000000 {

View file

@ -144,10 +144,10 @@ pcie: pcie@0x33800000 {
interrupt-names = "msi";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 2 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 3 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 4 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
interrupt-map = <0 0 0 1 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 2 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 3 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 4 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_PCIE_CTRL_ROOT_CLK>,
<&clks IMX7D_PLL_ENET_MAIN_100M_CLK>,
<&clks IMX7D_PCIE_PHY_ROOT_CLK>;

View file

@ -87,9 +87,10 @@ dma: dma@90500000 {
};
watchdog: watchdog@98500000 {
compatible = "moxa,moxart-watchdog";
compatible = "moxa,moxart-watchdog", "faraday,ftwdt010";
reg = <0x98500000 0x10>;
clocks = <&clk_apb>;
clock-names = "PCLK";
};
sdhci: sdhci@98e00000 {

View file

@ -1430,6 +1430,7 @@ adc: adc@fc030000 {
atmel,min-sample-rate-hz = <200000>;
atmel,max-sample-rate-hz = <20000000>;
atmel,startup-time-ms = <4>;
atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
status = "disabled";
};

View file

@ -311,8 +311,8 @@ tcon1_in: port@0 {
#size-cells = <0>;
reg = <0>;
tcon1_in_drc1: endpoint@0 {
reg = <0>;
tcon1_in_drc1: endpoint@1 {
reg = <1>;
remote-endpoint = <&drc1_out_tcon1>;
};
};
@ -1012,8 +1012,8 @@ be1_out: port@1 {
#size-cells = <0>;
reg = <1>;
be1_out_drc1: endpoint@0 {
reg = <0>;
be1_out_drc1: endpoint@1 {
reg = <1>;
remote-endpoint = <&drc1_in_be1>;
};
};
@ -1042,8 +1042,8 @@ drc1_in: port@0 {
#size-cells = <0>;
reg = <0>;
drc1_in_be1: endpoint@0 {
reg = <0>;
drc1_in_be1: endpoint@1 {
reg = <1>;
remote-endpoint = <&be1_out_drc1>;
};
};
@ -1053,8 +1053,8 @@ drc1_out: port@1 {
#size-cells = <0>;
reg = <1>;
drc1_out_tcon1: endpoint@0 {
reg = <0>;
drc1_out_tcon1: endpoint@1 {
reg = <1>;
remote-endpoint = <&tcon1_in_drc1>;
};
};

View file

@ -115,7 +115,11 @@ ENTRY(printascii)
mov r1, r0
mov r0, #0x04 @ SYS_WRITE0
ARM( svc #0x123456 )
#ifdef CONFIG_CPU_V7M
THUMB( bkpt #0xab )
#else
THUMB( svc #0xab )
#endif
ret lr
ENDPROC(printascii)
@ -124,7 +128,11 @@ ENTRY(printch)
strb r0, [r1]
mov r0, #0x03 @ SYS_WRITEC
ARM( svc #0x123456 )
#ifdef CONFIG_CPU_V7M
THUMB( bkpt #0xab )
#else
THUMB( svc #0xab )
#endif
ret lr
ENDPROC(printch)

View file

@ -32,6 +32,7 @@
#include <asm/mach/arch.h>
#include "db8500-regs.h"
#include "pm_domains.h"
static int __init ux500_l2x0_unlock(void)
{
@ -157,6 +158,9 @@ static const struct of_device_id u8500_local_bus_nodes[] = {
static void __init u8500_init_machine(void)
{
/* Initialize ux500 power domains */
ux500_pm_domains_init();
/* automatically probe child nodes of dbx5x0 devices */
if (of_machine_is_compatible("st-ericsson,u8540"))
of_platform_populate(NULL, u8500_local_bus_nodes,

View file

@ -19,7 +19,6 @@
#include <linux/of_address.h>
#include "db8500-regs.h"
#include "pm_domains.h"
/* ARM WFI Standby signal register */
#define PRCM_ARM_WFI_STANDBY (prcmu_base + 0x130)
@ -203,7 +202,4 @@ void __init ux500_pm_init(u32 phy_base, u32 size)
/* Set up ux500 suspend callbacks. */
suspend_set_ops(UX500_SUSPEND_OPS);
/* Initialize ux500 power domains */
ux500_pm_domains_init();
}

View file

@ -344,6 +344,11 @@ void __init arm_mm_memblock_reserve(void)
* reserved here.
*/
#endif
/*
* In any case, always ensure address 0 is never used as many things
* get very confused if 0 is returned as a legitimate address.
*/
memblock_reserve(0, 1);
}
void __init adjust_lowmem_bounds(void)

View file

@ -61,13 +61,6 @@ aliases {
chosen {
stdout-path = "serial0:115200n8";
};
reg_vcc3v3: vcc3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
};
&ehci0 {
@ -91,7 +84,7 @@ &i2c1_pins {
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
vmmc-supply = <&reg_vcc3v3>;
vmmc-supply = <&reg_dcdc1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
cd-inverted;
disable-wp;

View file

@ -336,7 +336,7 @@ cpm_pcie0: pcie@f2600000 {
/* non-prefetchable memory */
0x82000000 0 0xf6000000 0 0xf6000000 0 0xf00000>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &cpm_icu 0 ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
interrupt-map = <0 0 0 0 &cpm_icu ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
num-lanes = <1>;
clocks = <&cpm_clk 1 13>;
@ -362,7 +362,7 @@ cpm_pcie1: pcie@f2620000 {
/* non-prefetchable memory */
0x82000000 0 0xf7000000 0 0xf7000000 0 0xf00000>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &cpm_icu 0 ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
interrupt-map = <0 0 0 0 &cpm_icu ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
num-lanes = <1>;
@ -389,7 +389,7 @@ cpm_pcie2: pcie@f2640000 {
/* non-prefetchable memory */
0x82000000 0 0xf8000000 0 0xf8000000 0 0xf00000>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &cpm_icu 0 ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
interrupt-map = <0 0 0 0 &cpm_icu ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
num-lanes = <1>;

View file

@ -335,7 +335,7 @@ cps_pcie0: pcie@f4600000 {
/* non-prefetchable memory */
0x82000000 0 0xfa000000 0 0xfa000000 0 0xf00000>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &cps_icu 0 ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
interrupt-map = <0 0 0 0 &cps_icu ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
num-lanes = <1>;
clocks = <&cps_clk 1 13>;
@ -361,7 +361,7 @@ cps_pcie1: pcie@f4620000 {
/* non-prefetchable memory */
0x82000000 0 0xfb000000 0 0xfb000000 0 0xf00000>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &cps_icu 0 ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
interrupt-map = <0 0 0 0 &cps_icu ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
num-lanes = <1>;
@ -388,7 +388,7 @@ cps_pcie2: pcie@f4640000 {
/* non-prefetchable memory */
0x82000000 0 0xfc000000 0 0xfc000000 0 0xf00000>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &cps_icu 0 ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
interrupt-map = <0 0 0 0 &cps_icu ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
num-lanes = <1>;

View file

@ -62,6 +62,7 @@ backlight: backlight {
brightness-levels = <256 128 64 16 8 4 0>;
default-brightness-level = <6>;
power-supply = <&reg_12v>;
enable-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
};
@ -83,6 +84,15 @@ reg_3p3v: regulator1 {
regulator-always-on;
};
reg_12v: regulator2 {
compatible = "regulator-fixed";
regulator-name = "fixed-12V";
regulator-min-microvolt = <12000000>;
regulator-max-microvolt = <12000000>;
regulator-boot-on;
regulator-always-on;
};
rsnd_ak4613: sound {
compatible = "simple-audio-card";

View file

@ -582,7 +582,7 @@ rkvdec_mmu: iommu@ff360480 {
vop_mmu: iommu@ff373f00 {
compatible = "rockchip,iommu";
reg = <0x0 0xff373f00 0x0 0x100>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH 0>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vop_mmu";
#iommu-cells = <0>;
status = "disabled";

View file

@ -740,7 +740,7 @@ i2s_8ch: i2s-8ch@ff898000 {
iep_mmu: iommu@ff900800 {
compatible = "rockchip,iommu";
reg = <0x0 0xff900800 0x0 0x100>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH 0>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "iep_mmu";
#iommu-cells = <0>;
status = "disabled";

View file

@ -371,10 +371,10 @@ vcc_sdio: LDO_REG4 {
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-max-microvolt = <3000000>;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
regulator-suspend-microvolt = <3000000>;
};
};

View file

@ -325,12 +325,12 @@ regulator-state-mem {
vcc_sd: LDO_REG4 {
regulator-name = "vcc_sd";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-max-microvolt = <3000000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
regulator-suspend-microvolt = <3000000>;
};
};

View file

@ -315,10 +315,10 @@ vcc_sdio: LDO_REG4 {
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-max-microvolt = <3000000>;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
regulator-suspend-microvolt = <3000000>;
};
};

View file

@ -546,9 +546,6 @@ static int bts_event_init(struct perf_event *event)
if (event->attr.type != bts_pmu.type)
return -ENOENT;
if (x86_add_exclusive(x86_lbr_exclusive_bts))
return -EBUSY;
/*
* BTS leaks kernel addresses even when CPL0 tracing is
* disabled, so disallow intel_bts driver for unprivileged
@ -562,6 +559,9 @@ static int bts_event_init(struct perf_event *event)
!capable(CAP_SYS_ADMIN))
return -EACCES;
if (x86_add_exclusive(x86_lbr_exclusive_bts))
return -EBUSY;
ret = x86_reserve_hardware();
if (ret) {
x86_del_exclusive(x86_lbr_exclusive_bts);

View file

@ -110,6 +110,10 @@ build_mmio_write(__writeq, "q", unsigned long, "r", )
#endif
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
/**
* virt_to_phys - map virtual addresses to physical
* @address: address to remap

View file

@ -82,12 +82,21 @@ static inline u64 inc_mm_tlb_gen(struct mm_struct *mm)
#define __flush_tlb_single(addr) __native_flush_tlb_single(addr)
#endif
/*
* If tlb_use_lazy_mode is true, then we try to avoid switching CR3 to point
* to init_mm when we switch to a kernel thread (e.g. the idle thread). If
* it's false, then we immediately switch CR3 when entering a kernel thread.
*/
DECLARE_STATIC_KEY_TRUE(tlb_use_lazy_mode);
static inline bool tlb_defer_switch_to_init_mm(void)
{
/*
* If we have PCID, then switching to init_mm is reasonably
* fast. If we don't have PCID, then switching to init_mm is
* quite slow, so we try to defer it in the hopes that we can
* avoid it entirely. The latter approach runs the risk of
* receiving otherwise unnecessary IPIs.
*
* This choice is just a heuristic. The tlb code can handle this
* function returning true or false regardless of whether we have
* PCID.
*/
return !static_cpu_has(X86_FEATURE_PCID);
}
/*
* 6 because 6 should be plenty and struct tlb_state will fit in

View file

@ -831,7 +831,6 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
} else if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
unsigned int apicid, nshared, first, last;
this_leaf = this_cpu_ci->info_list + index;
nshared = base->eax.split.num_threads_sharing + 1;
apicid = cpu_data(cpu).apicid;
first = apicid - (apicid % nshared);

View file

@ -34,6 +34,7 @@
#include <linux/mm.h>
#include <asm/microcode_intel.h>
#include <asm/intel-family.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/setup.h>
@ -918,6 +919,18 @@ static int get_ucode_fw(void *to, const void *from, size_t n)
return 0;
}
static bool is_blacklisted(unsigned int cpu)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
if (c->x86 == 6 && c->x86_model == INTEL_FAM6_BROADWELL_X) {
pr_err_once("late loading on model 79 is disabled.\n");
return true;
}
return false;
}
static enum ucode_state request_microcode_fw(int cpu, struct device *device,
bool refresh_fw)
{
@ -926,6 +939,9 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
const struct firmware *firmware;
enum ucode_state ret;
if (is_blacklisted(cpu))
return UCODE_NFOUND;
sprintf(name, "intel-ucode/%02x-%02x-%02x",
c->x86, c->x86_model, c->x86_mask);
@ -950,6 +966,9 @@ static int get_ucode_user(void *to, const void *from, size_t n)
static enum ucode_state
request_microcode_user(int cpu, const void __user *buf, size_t size)
{
if (is_blacklisted(cpu))
return UCODE_NFOUND;
return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
}

View file

@ -30,10 +30,11 @@ static void __init i386_default_early_setup(void)
asmlinkage __visible void __init i386_start_kernel(void)
{
cr4_init_shadow();
/* Make sure IDT is set up before any exception happens */
idt_setup_early_handler();
cr4_init_shadow();
sanitize_boot_params(&boot_params);
x86_early_init_platform_quirks();

View file

@ -174,3 +174,15 @@ const char *arch_vma_name(struct vm_area_struct *vma)
return "[mpx]";
return NULL;
}
int valid_phys_addr_range(phys_addr_t addr, size_t count)
{
return addr + count <= __pa(high_memory);
}
int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
{
phys_addr_t addr = (phys_addr_t)pfn << PAGE_SHIFT;
return valid_phys_addr_range(addr, count);
}

View file

@ -30,7 +30,6 @@
atomic64_t last_mm_ctx_id = ATOMIC64_INIT(1);
DEFINE_STATIC_KEY_TRUE(tlb_use_lazy_mode);
static void choose_new_asid(struct mm_struct *next, u64 next_tlb_gen,
u16 *new_asid, bool *need_flush)
@ -147,8 +146,8 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
this_cpu_write(cpu_tlbstate.is_lazy, false);
if (real_prev == next) {
VM_BUG_ON(this_cpu_read(cpu_tlbstate.ctxs[prev_asid].ctx_id) !=
next->context.ctx_id);
VM_WARN_ON(this_cpu_read(cpu_tlbstate.ctxs[prev_asid].ctx_id) !=
next->context.ctx_id);
/*
* We don't currently support having a real mm loaded without
@ -213,6 +212,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
}
/*
* Please ignore the name of this function. It should be called
* switch_to_kernel_thread().
*
* enter_lazy_tlb() is a hint from the scheduler that we are entering a
* kernel thread or other context without an mm. Acceptable implementations
* include doing nothing whatsoever, switching to init_mm, or various clever
@ -227,7 +229,7 @@ void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm)
return;
if (static_branch_unlikely(&tlb_use_lazy_mode)) {
if (tlb_defer_switch_to_init_mm()) {
/*
* There's a significant optimization that may be possible
* here. We have accurate enough TLB flush tracking that we
@ -626,57 +628,3 @@ static int __init create_tlb_single_page_flush_ceiling(void)
return 0;
}
late_initcall(create_tlb_single_page_flush_ceiling);
static ssize_t tlblazy_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
char buf[2];
buf[0] = static_branch_likely(&tlb_use_lazy_mode) ? '1' : '0';
buf[1] = '\n';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
static ssize_t tlblazy_write_file(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
bool val;
if (kstrtobool_from_user(user_buf, count, &val))
return -EINVAL;
if (val)
static_branch_enable(&tlb_use_lazy_mode);
else
static_branch_disable(&tlb_use_lazy_mode);
return count;
}
static const struct file_operations fops_tlblazy = {
.read = tlblazy_read_file,
.write = tlblazy_write_file,
.llseek = default_llseek,
};
static int __init init_tlb_use_lazy_mode(void)
{
if (boot_cpu_has(X86_FEATURE_PCID)) {
/*
* Heuristic: with PCID on, switching to and from
* init_mm is reasonably fast, but remote flush IPIs
* as expensive as ever, so turn off lazy TLB mode.
*
* We can't do this in setup_pcid() because static keys
* haven't been initialized yet, and it would blow up
* badly.
*/
static_branch_disable(&tlb_use_lazy_mode);
}
debugfs_create_file("tlb_use_lazy_mode", S_IRUSR | S_IWUSR,
arch_debugfs_dir, NULL, &fops_tlblazy);
return 0;
}
late_initcall(init_tlb_use_lazy_mode);

View file

@ -57,6 +57,8 @@ struct key *find_asymmetric_key(struct key *keyring,
char *req, *p;
int len;
BUG_ON(!id_0 && !id_1);
if (id_0) {
lookup = id_0->data;
len = id_0->len;
@ -105,7 +107,7 @@ struct key *find_asymmetric_key(struct key *keyring,
if (id_0 && id_1) {
const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
if (!kids->id[0]) {
if (!kids->id[1]) {
pr_debug("First ID matches, but second is missing\n");
goto reject;
}

View file

@ -88,6 +88,9 @@ static int pkcs7_check_authattrs(struct pkcs7_message *msg)
bool want = false;
sinfo = msg->signed_infos;
if (!sinfo)
goto inconsistent;
if (sinfo->authattrs) {
want = true;
msg->have_authattrs = true;

View file

@ -3662,12 +3662,6 @@ static void binder_stat_br(struct binder_proc *proc,
}
}
static int binder_has_thread_work(struct binder_thread *thread)
{
return !binder_worklist_empty(thread->proc, &thread->todo) ||
thread->looper_need_return;
}
static int binder_put_node_cmd(struct binder_proc *proc,
struct binder_thread *thread,
void __user **ptrp,
@ -4297,12 +4291,9 @@ static unsigned int binder_poll(struct file *filp,
binder_inner_proc_unlock(thread->proc);
if (binder_has_work(thread, wait_for_proc_work))
return POLLIN;
poll_wait(filp, &thread->wait, wait);
if (binder_has_thread_work(thread))
if (binder_has_work(thread, wait_for_proc_work))
return POLLIN;
return 0;

View file

@ -215,17 +215,12 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
}
}
if (!vma && need_mm)
mm = get_task_mm(alloc->tsk);
if (!vma && need_mm && mmget_not_zero(alloc->vma_vm_mm))
mm = alloc->vma_vm_mm;
if (mm) {
down_write(&mm->mmap_sem);
vma = alloc->vma;
if (vma && mm != alloc->vma_vm_mm) {
pr_err("%d: vma mm and task mm mismatch\n",
alloc->pid);
vma = NULL;
}
}
if (!vma && need_mm) {
@ -565,7 +560,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc,
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: merge free, buffer %pK do not share page with %pK or %pK\n",
alloc->pid, buffer->data,
prev->data, next->data);
prev->data, next ? next->data : NULL);
binder_update_page_range(alloc, 0, buffer_start_page(buffer),
buffer_start_page(buffer) + PAGE_SIZE,
NULL);
@ -720,6 +715,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
barrier();
alloc->vma = vma;
alloc->vma_vm_mm = vma->vm_mm;
mmgrab(alloc->vma_vm_mm);
return 0;
@ -795,6 +791,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
vfree(alloc->buffer);
}
mutex_unlock(&alloc->mutex);
if (alloc->vma_vm_mm)
mmdrop(alloc->vma_vm_mm);
binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE,
"%s: %d buffers %d, pages %d\n",
@ -889,7 +887,6 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc)
void binder_alloc_vma_close(struct binder_alloc *alloc)
{
WRITE_ONCE(alloc->vma, NULL);
WRITE_ONCE(alloc->vma_vm_mm, NULL);
}
/**
@ -926,9 +923,9 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;
vma = alloc->vma;
if (vma) {
mm = get_task_mm(alloc->tsk);
if (!mm)
goto err_get_task_mm_failed;
if (!mmget_not_zero(alloc->vma_vm_mm))
goto err_mmget;
mm = alloc->vma_vm_mm;
if (!down_write_trylock(&mm->mmap_sem))
goto err_down_write_mmap_sem_failed;
}
@ -963,7 +960,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
err_down_write_mmap_sem_failed:
mmput_async(mm);
err_get_task_mm_failed:
err_mmget:
err_page_already_freed:
mutex_unlock(&alloc->mutex);
err_get_alloc_mutex_failed:
@ -1002,7 +999,6 @@ struct shrinker binder_shrinker = {
*/
void binder_alloc_init(struct binder_alloc *alloc)
{
alloc->tsk = current->group_leader;
alloc->pid = current->group_leader->pid;
mutex_init(&alloc->mutex);
INIT_LIST_HEAD(&alloc->buffers);

View file

@ -100,7 +100,6 @@ struct binder_lru_page {
*/
struct binder_alloc {
struct mutex mutex;
struct task_struct *tsk;
struct vm_area_struct *vma;
struct mm_struct *vma_vm_mm;
void *buffer;

View file

@ -720,7 +720,7 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
if (mbus->hw_io_coherency)
w->mbus_attr |= ATTR_HW_COHERENCY;
w->base = base & DDR_BASE_CS_LOW_MASK;
w->size = (size | ~DDR_SIZE_MASK) + 1;
w->size = (u64)(size | ~DDR_SIZE_MASK) + 1;
}
}
mvebu_mbus_dram_info.num_cs = cs;

View file

@ -117,7 +117,8 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id)
/* Turn off the clock (and clear the event) */
disable_timer(cs5535_event_clock);
if (clockevent_state_shutdown(&cs5535_clockevent))
if (clockevent_state_detached(&cs5535_clockevent) ||
clockevent_state_shutdown(&cs5535_clockevent))
return IRQ_HANDLED;
/* Clear the counter */

View file

@ -344,7 +344,7 @@ msgdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
spin_lock_irqsave(&mdev->lock, irqflags);
if (desc_cnt > mdev->desc_free_cnt) {
spin_unlock_bh(&mdev->lock);
spin_unlock_irqrestore(&mdev->lock, irqflags);
dev_dbg(mdev->dev, "mdev %p descs are not available\n", mdev);
return NULL;
}
@ -407,7 +407,7 @@ msgdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
spin_lock_irqsave(&mdev->lock, irqflags);
if (desc_cnt > mdev->desc_free_cnt) {
spin_unlock_bh(&mdev->lock);
spin_unlock_irqrestore(&mdev->lock, irqflags);
dev_dbg(mdev->dev, "mdev %p descs are not available\n", mdev);
return NULL;
}

View file

@ -205,32 +205,17 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
struct amd_sched_entity *entity)
{
struct amd_sched_rq *rq = entity->rq;
int r;
if (!amd_sched_entity_is_initialized(sched, entity))
return;
/**
* The client will not queue more IBs during this fini, consume existing
* queued IBs or discard them on SIGKILL
* queued IBs
*/
if ((current->flags & PF_SIGNALED) && current->exit_code == SIGKILL)
r = -ERESTARTSYS;
else
r = wait_event_killable(sched->job_scheduled,
amd_sched_entity_is_idle(entity));
wait_event(sched->job_scheduled, amd_sched_entity_is_idle(entity));
amd_sched_rq_remove_entity(rq, entity);
if (r) {
struct amd_sched_job *job;
/* Park the kernel for a moment to make sure it isn't processing
* our enity.
*/
kthread_park(sched->thread);
kthread_unpark(sched->thread);
while (kfifo_out(&entity->job_queue, &job, sizeof(job)))
sched->ops->free_job(job);
}
kfifo_free(&entity->job_queue);
}

View file

@ -168,11 +168,13 @@ static struct drm_driver exynos_drm_driver = {
static int exynos_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct exynos_drm_private *private = drm_dev->dev_private;
struct exynos_drm_private *private;
if (pm_runtime_suspended(dev) || !drm_dev)
return 0;
private = drm_dev->dev_private;
drm_kms_helper_poll_disable(drm_dev);
exynos_drm_fbdev_suspend(drm_dev);
private->suspend_state = drm_atomic_helper_suspend(drm_dev);
@ -188,11 +190,12 @@ static int exynos_drm_suspend(struct device *dev)
static int exynos_drm_resume(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct exynos_drm_private *private = drm_dev->dev_private;
struct exynos_drm_private *private;
if (pm_runtime_suspended(dev) || !drm_dev)
return 0;
private = drm_dev->dev_private;
drm_atomic_helper_resume(drm_dev, private->suspend_state);
exynos_drm_fbdev_resume(drm_dev);
drm_kms_helper_poll_enable(drm_dev);
@ -427,6 +430,7 @@ static void exynos_drm_unbind(struct device *dev)
kfree(drm->dev_private);
drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
drm_dev_unref(drm);
}

View file

@ -308,20 +308,8 @@ static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu)
static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu)
{
struct intel_gvt_workload_scheduler *scheduler = &vgpu->gvt->scheduler;
int ring_id;
kfree(vgpu->sched_data);
vgpu->sched_data = NULL;
spin_lock_bh(&scheduler->mmio_context_lock);
for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) {
if (scheduler->engine_owner[ring_id] == vgpu) {
intel_gvt_switch_mmio(vgpu, NULL, ring_id);
scheduler->engine_owner[ring_id] = NULL;
}
}
spin_unlock_bh(&scheduler->mmio_context_lock);
}
static void tbs_sched_start_schedule(struct intel_vgpu *vgpu)
@ -388,6 +376,7 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
{
struct intel_gvt_workload_scheduler *scheduler =
&vgpu->gvt->scheduler;
int ring_id;
gvt_dbg_core("vgpu%d: stop schedule\n", vgpu->id);
@ -401,4 +390,13 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
scheduler->need_reschedule = true;
scheduler->current_vgpu = NULL;
}
spin_lock_bh(&scheduler->mmio_context_lock);
for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) {
if (scheduler->engine_owner[ring_id] == vgpu) {
intel_gvt_switch_mmio(vgpu, NULL, ring_id);
scheduler->engine_owner[ring_id] = NULL;
}
}
spin_unlock_bh(&scheduler->mmio_context_lock);
}

View file

@ -2657,6 +2657,9 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
if (READ_ONCE(obj->mm.pages))
return -ENODEV;
if (obj->mm.madv != I915_MADV_WILLNEED)
return -EFAULT;
/* Before the pages are instantiated the object is treated as being
* in the CPU domain. The pages will be clflushed as required before
* use, and we can freely write into the pages directly. If userspace

View file

@ -33,21 +33,20 @@
#include "intel_drv.h"
#include "i915_trace.h"
static bool ggtt_is_idle(struct drm_i915_private *dev_priv)
static bool ggtt_is_idle(struct drm_i915_private *i915)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct intel_engine_cs *engine;
enum intel_engine_id id;
struct intel_engine_cs *engine;
enum intel_engine_id id;
for_each_engine(engine, dev_priv, id) {
struct intel_timeline *tl;
if (i915->gt.active_requests)
return false;
tl = &ggtt->base.timeline.engine[engine->id];
if (i915_gem_active_isset(&tl->last_request))
return false;
}
for_each_engine(engine, i915, id) {
if (engine->last_retired_context != i915->kernel_context)
return false;
}
return true;
return true;
}
static int ggtt_flush(struct drm_i915_private *i915)
@ -157,7 +156,8 @@ i915_gem_evict_something(struct i915_address_space *vm,
min_size, alignment, cache_level,
start, end, mode);
/* Retire before we search the active list. Although we have
/*
* Retire before we search the active list. Although we have
* reasonable accuracy in our retirement lists, we may have
* a stray pin (preventing eviction) that can only be resolved by
* retiring.
@ -182,7 +182,8 @@ i915_gem_evict_something(struct i915_address_space *vm,
BUG_ON(ret);
}
/* Can we unpin some objects such as idle hw contents,
/*
* Can we unpin some objects such as idle hw contents,
* or pending flips? But since only the GGTT has global entries
* such as scanouts, rinbuffers and contexts, we can skip the
* purge when inspecting per-process local address spaces.
@ -190,19 +191,33 @@ i915_gem_evict_something(struct i915_address_space *vm,
if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK)
return -ENOSPC;
if (ggtt_is_idle(dev_priv)) {
/* If we still have pending pageflip completions, drop
* back to userspace to give our workqueues time to
* acquire our locks and unpin the old scanouts.
*/
return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC;
/*
* Not everything in the GGTT is tracked via VMA using
* i915_vma_move_to_active(), otherwise we could evict as required
* with minimal stalling. Instead we are forced to idle the GPU and
* explicitly retire outstanding requests which will then remove
* the pinning for active objects such as contexts and ring,
* enabling us to evict them on the next iteration.
*
* To ensure that all user contexts are evictable, we perform
* a switch to the perma-pinned kernel context. This all also gives
* us a termination condition, when the last retired context is
* the kernel's there is no more we can evict.
*/
if (!ggtt_is_idle(dev_priv)) {
ret = ggtt_flush(dev_priv);
if (ret)
return ret;
goto search_again;
}
ret = ggtt_flush(dev_priv);
if (ret)
return ret;
goto search_again;
/*
* If we still have pending pageflip completions, drop
* back to userspace to give our workqueues time to
* acquire our locks and unpin the old scanouts.
*/
return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC;
found:
/* drm_mm doesn't allow any other other operations while

View file

@ -6998,6 +6998,7 @@ enum {
*/
#define L3_GENERAL_PRIO_CREDITS(x) (((x) >> 1) << 19)
#define L3_HIGH_PRIO_CREDITS(x) (((x) >> 1) << 14)
#define L3_PRIO_CREDITS_MASK ((0x1f << 19) | (0x1f << 14))
#define GEN7_L3CNTLREG1 _MMIO(0xB01C)
#define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C

View file

@ -664,8 +664,8 @@ intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv,
int *n_entries)
{
if (IS_BROADWELL(dev_priv)) {
*n_entries = ARRAY_SIZE(hsw_ddi_translations_fdi);
return hsw_ddi_translations_fdi;
*n_entries = ARRAY_SIZE(bdw_ddi_translations_fdi);
return bdw_ddi_translations_fdi;
} else if (IS_HASWELL(dev_priv)) {
*n_entries = ARRAY_SIZE(hsw_ddi_translations_fdi);
return hsw_ddi_translations_fdi;
@ -2102,8 +2102,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
* register writes.
*/
val = I915_READ(DPCLKA_CFGCR0);
val &= ~(DPCLKA_CFGCR0_DDI_CLK_OFF(port) |
DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port));
val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
I915_WRITE(DPCLKA_CFGCR0, val);
} else if (IS_GEN9_BC(dev_priv)) {
/* DDI -> PLL mapping */

View file

@ -1996,7 +1996,7 @@ static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv,
/* 3. Configure DPLL_CFGCR0 */
/* Avoid touch CFGCR1 if HDMI mode is not enabled */
if (pll->state.hw_state.cfgcr0 & DPLL_CTRL1_HDMI_MODE(pll->id)) {
if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
val = pll->state.hw_state.cfgcr1;
I915_WRITE(CNL_DPLL_CFGCR1(pll->id), val);
/* 4. Reab back to ensure writes completed */

View file

@ -1048,9 +1048,12 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine)
}
/* WaProgramL3SqcReg1DefaultForPerf:bxt */
if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER))
I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) |
L3_HIGH_PRIO_CREDITS(2));
if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
u32 val = I915_READ(GEN8_L3SQCREG1);
val &= ~L3_PRIO_CREDITS_MASK;
val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2);
I915_WRITE(GEN8_L3SQCREG1, val);
}
/* WaToEnableHwFixForPushConstHWBug:bxt */
if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))

View file

@ -8245,14 +8245,17 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv,
int high_prio_credits)
{
u32 misccpctl;
u32 val;
/* WaTempDisableDOPClkGating:bdw */
misccpctl = I915_READ(GEN7_MISCCPCTL);
I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
I915_WRITE(GEN8_L3SQCREG1,
L3_GENERAL_PRIO_CREDITS(general_prio_credits) |
L3_HIGH_PRIO_CREDITS(high_prio_credits));
val = I915_READ(GEN8_L3SQCREG1);
val &= ~L3_PRIO_CREDITS_MASK;
val |= L3_GENERAL_PRIO_CREDITS(general_prio_credits);
val |= L3_HIGH_PRIO_CREDITS(high_prio_credits);
I915_WRITE(GEN8_L3SQCREG1, val);
/*
* Wait at least 100 clocks before re-enabling clock gating.

View file

@ -223,7 +223,7 @@ void
nouveau_fbcon_accel_save_disable(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
if (drm->fbcon) {
if (drm->fbcon && drm->fbcon->helper.fbdev) {
drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags;
drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
}
@ -233,7 +233,7 @@ void
nouveau_fbcon_accel_restore(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
if (drm->fbcon) {
if (drm->fbcon && drm->fbcon->helper.fbdev) {
drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags;
}
}
@ -245,7 +245,8 @@ nouveau_fbcon_accel_fini(struct drm_device *dev)
struct nouveau_fbdev *fbcon = drm->fbcon;
if (fbcon && drm->channel) {
console_lock();
fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
if (fbcon->helper.fbdev)
fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
console_unlock();
nouveau_channel_idle(drm->channel);
nvif_object_fini(&fbcon->twod);

View file

@ -3265,11 +3265,14 @@ nv50_mstm = {
void
nv50_mstm_service(struct nv50_mstm *mstm)
{
struct drm_dp_aux *aux = mstm->mgr.aux;
struct drm_dp_aux *aux = mstm ? mstm->mgr.aux : NULL;
bool handled = true;
int ret;
u8 esi[8] = {};
if (!aux)
return;
while (handled) {
ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8);
if (ret != 8) {

View file

@ -39,5 +39,5 @@ int
g84_bsp_new(struct nvkm_device *device, int index, struct nvkm_engine **pengine)
{
return nvkm_xtensa_new_(&g84_bsp, device, index,
true, 0x103000, pengine);
device->chipset != 0x92, 0x103000, pengine);
}

View file

@ -241,6 +241,8 @@ nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde)
mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem);
}
mmu->func->flush(vm);
nvkm_memory_del(&pgt);
}
}

View file

@ -937,7 +937,10 @@ void vmbus_hvsock_device_unregister(struct vmbus_channel *channel)
{
BUG_ON(!is_hvsock_channel(channel));
channel->rescind = true;
/* We always get a rescind msg when a connection is closed. */
while (!READ_ONCE(channel->probe_done) || !READ_ONCE(channel->rescind))
msleep(1);
vmbus_device_unregister(channel->device_obj);
}
EXPORT_SYMBOL_GPL(vmbus_hvsock_device_unregister);

View file

@ -1021,7 +1021,7 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
}
dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n",
rinfo->sda_gpio, rinfo->scl_gpio);
rinfo->scl_gpio, rinfo->sda_gpio);
rinfo->prepare_recovery = i2c_imx_prepare_recovery;
rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
@ -1100,7 +1100,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
}
/* Request IRQ */
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_SHARED,
pdev->name, i2c_imx);
if (ret) {
dev_err(&pdev->dev, "can't claim irq %d\n", irq);

View file

@ -340,12 +340,15 @@ static int ismt_process_desc(const struct ismt_desc *desc,
data->word = dma_buffer[0] | (dma_buffer[1] << 8);
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_I2C_BLOCK_DATA:
if (desc->rxbytes != dma_buffer[0] + 1)
return -EMSGSIZE;
memcpy(data->block, dma_buffer, desc->rxbytes);
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
memcpy(&data->block[1], dma_buffer, desc->rxbytes);
data->block[0] = desc->rxbytes;
break;
}
return 0;
}

View file

@ -360,6 +360,7 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
unsigned long fclk_rate = 12000000;
unsigned long internal_clk = 0;
struct clk *fclk;
int error;
if (omap->rev >= OMAP_I2C_REV_ON_3430_3530) {
/*
@ -378,6 +379,13 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
* do this bit unconditionally.
*/
fclk = clk_get(omap->dev, "fck");
if (IS_ERR(fclk)) {
error = PTR_ERR(fclk);
dev_err(omap->dev, "could not get fck: %i\n", error);
return error;
}
fclk_rate = clk_get_rate(fclk);
clk_put(fclk);
@ -410,6 +418,12 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
else
internal_clk = 4000;
fclk = clk_get(omap->dev, "fck");
if (IS_ERR(fclk)) {
error = PTR_ERR(fclk);
dev_err(omap->dev, "could not get fck: %i\n", error);
return error;
}
fclk_rate = clk_get_rate(fclk) / 1000;
clk_put(fclk);

View file

@ -85,6 +85,9 @@
/* SB800 constants */
#define SB800_PIIX4_SMB_IDX 0xcd6
#define KERNCZ_IMC_IDX 0x3e
#define KERNCZ_IMC_DATA 0x3f
/*
* SB800 port is selected by bits 2:1 of the smb_en register (0x2c)
* or the smb_sel register (0x2e), depending on bit 0 of register 0x2f.
@ -94,6 +97,12 @@
#define SB800_PIIX4_PORT_IDX_ALT 0x2e
#define SB800_PIIX4_PORT_IDX_SEL 0x2f
#define SB800_PIIX4_PORT_IDX_MASK 0x06
#define SB800_PIIX4_PORT_IDX_SHIFT 1
/* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */
#define SB800_PIIX4_PORT_IDX_KERNCZ 0x02
#define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18
#define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3
/* insmod parameters */
@ -149,6 +158,8 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
*/
static DEFINE_MUTEX(piix4_mutex_sb800);
static u8 piix4_port_sel_sb800;
static u8 piix4_port_mask_sb800;
static u8 piix4_port_shift_sb800;
static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = {
" port 0", " port 2", " port 3", " port 4"
};
@ -159,6 +170,7 @@ struct i2c_piix4_adapdata {
/* SB800 */
bool sb800_main;
bool notify_imc;
u8 port; /* Port number, shifted */
};
@ -347,7 +359,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
/* Find which register is used for port selection */
if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD) {
piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT;
switch (PIIX4_dev->device) {
case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS:
piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ;
break;
case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS:
default:
piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
break;
}
} else {
mutex_lock(&piix4_mutex_sb800);
outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
@ -355,6 +379,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
piix4_port_sel_sb800 = (port_sel & 0x01) ?
SB800_PIIX4_PORT_IDX_ALT :
SB800_PIIX4_PORT_IDX;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
mutex_unlock(&piix4_mutex_sb800);
}
@ -572,6 +598,67 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
return 0;
}
static uint8_t piix4_imc_read(uint8_t idx)
{
outb_p(idx, KERNCZ_IMC_IDX);
return inb_p(KERNCZ_IMC_DATA);
}
static void piix4_imc_write(uint8_t idx, uint8_t value)
{
outb_p(idx, KERNCZ_IMC_IDX);
outb_p(value, KERNCZ_IMC_DATA);
}
static int piix4_imc_sleep(void)
{
int timeout = MAX_TIMEOUT;
if (!request_muxed_region(KERNCZ_IMC_IDX, 2, "smbus_kerncz_imc"))
return -EBUSY;
/* clear response register */
piix4_imc_write(0x82, 0x00);
/* request ownership flag */
piix4_imc_write(0x83, 0xB4);
/* kick off IMC Mailbox command 96 */
piix4_imc_write(0x80, 0x96);
while (timeout--) {
if (piix4_imc_read(0x82) == 0xfa) {
release_region(KERNCZ_IMC_IDX, 2);
return 0;
}
usleep_range(1000, 2000);
}
release_region(KERNCZ_IMC_IDX, 2);
return -ETIMEDOUT;
}
static void piix4_imc_wakeup(void)
{
int timeout = MAX_TIMEOUT;
if (!request_muxed_region(KERNCZ_IMC_IDX, 2, "smbus_kerncz_imc"))
return;
/* clear response register */
piix4_imc_write(0x82, 0x00);
/* release ownership flag */
piix4_imc_write(0x83, 0xB5);
/* kick off IMC Mailbox command 96 */
piix4_imc_write(0x80, 0x96);
while (timeout--) {
if (piix4_imc_read(0x82) == 0xfa)
break;
usleep_range(1000, 2000);
}
release_region(KERNCZ_IMC_IDX, 2);
}
/*
* Handles access to multiple SMBus ports on the SB800.
* The port is selected by bits 2:1 of the smb_en register (0x2c).
@ -612,12 +699,47 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
return -EBUSY;
}
/*
* Notify the IMC (Integrated Micro Controller) if required.
* Among other responsibilities, the IMC is in charge of monitoring
* the System fans and temperature sensors, and act accordingly.
* All this is done through SMBus and can/will collide
* with our transactions if they are long (BLOCK_DATA).
* Therefore we need to request the ownership flag during those
* transactions.
*/
if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) {
int ret;
ret = piix4_imc_sleep();
switch (ret) {
case -EBUSY:
dev_warn(&adap->dev,
"IMC base address index region 0x%x already in use.\n",
KERNCZ_IMC_IDX);
break;
case -ETIMEDOUT:
dev_warn(&adap->dev,
"Failed to communicate with the IMC.\n");
break;
default:
break;
}
/* If IMC communication fails do not retry */
if (ret) {
dev_warn(&adap->dev,
"Continuing without IMC notification.\n");
adapdata->notify_imc = false;
}
}
outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
port = adapdata->port;
if ((smba_en_lo & SB800_PIIX4_PORT_IDX_MASK) != port)
outb_p((smba_en_lo & ~SB800_PIIX4_PORT_IDX_MASK) | port,
if ((smba_en_lo & piix4_port_mask_sb800) != port)
outb_p((smba_en_lo & ~piix4_port_mask_sb800) | port,
SB800_PIIX4_SMB_IDX + 1);
retval = piix4_access(adap, addr, flags, read_write,
@ -628,6 +750,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
/* Release the semaphore */
outb_p(smbslvcnt | 0x20, SMBSLVCNT);
if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc)
piix4_imc_wakeup();
mutex_unlock(&piix4_mutex_sb800);
return retval;
@ -679,7 +804,7 @@ static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS];
static struct i2c_adapter *piix4_aux_adapter;
static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
bool sb800_main, u8 port,
bool sb800_main, u8 port, bool notify_imc,
const char *name, struct i2c_adapter **padap)
{
struct i2c_adapter *adap;
@ -706,7 +831,8 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
adapdata->smba = smba;
adapdata->sb800_main = sb800_main;
adapdata->port = port << 1;
adapdata->port = port << piix4_port_shift_sb800;
adapdata->notify_imc = notify_imc;
/* set up the sysfs linkage to our parent device */
adap->dev.parent = &dev->dev;
@ -728,14 +854,15 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
return 0;
}
static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba)
static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba,
bool notify_imc)
{
struct i2c_piix4_adapdata *adapdata;
int port;
int retval;
for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) {
retval = piix4_add_adapter(dev, smba, true, port,
retval = piix4_add_adapter(dev, smba, true, port, notify_imc,
piix4_main_port_names_sb800[port],
&piix4_main_adapters[port]);
if (retval < 0)
@ -769,6 +896,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
dev->revision >= 0x40) ||
dev->vendor == PCI_VENDOR_ID_AMD) {
bool notify_imc = false;
is_sb800 = true;
if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
@ -778,6 +906,20 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -EBUSY;
}
if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) {
u8 imc;
/*
* Detect if IMC is active or not, this method is
* described on coreboot's AMD IMC notes
*/
pci_bus_read_config_byte(dev->bus, PCI_DEVFN(0x14, 3),
0x40, &imc);
if (imc & 0x80)
notify_imc = true;
}
/* base address location etc changed in SB800 */
retval = piix4_setup_sb800(dev, id, 0);
if (retval < 0) {
@ -789,7 +931,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
* Try to register multiplexed main SMBus adapter,
* give up if we can't
*/
retval = piix4_add_adapters_sb800(dev, retval);
retval = piix4_add_adapters_sb800(dev, retval, notify_imc);
if (retval < 0) {
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval;
@ -800,7 +942,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
return retval;
/* Try to register main SMBus adapter, give up if we can't */
retval = piix4_add_adapter(dev, retval, false, 0, "",
retval = piix4_add_adapter(dev, retval, false, 0, false, "",
&piix4_main_adapters[0]);
if (retval < 0)
return retval;
@ -827,7 +969,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (retval > 0) {
/* Try to add the aux adapter if it exists,
* piix4_add_adapter will clean up if this fails */
piix4_add_adapter(dev, retval, false, 0,
piix4_add_adapter(dev, retval, false, 0, false,
is_sb800 ? piix4_aux_port_name_sb800 : "",
&piix4_aux_adapter);
}

View file

@ -243,6 +243,8 @@ config DA9150_GPADC
config DLN2_ADC
tristate "Diolan DLN-2 ADC driver support"
depends on MFD_DLN2
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Diolan DLN-2 ADC.

View file

@ -225,6 +225,7 @@ struct at91_adc_trigger {
char *name;
unsigned int trgmod_value;
unsigned int edge_type;
bool hw_trig;
};
struct at91_adc_state {
@ -254,16 +255,25 @@ static const struct at91_adc_trigger at91_adc_trigger_list[] = {
.name = "external_rising",
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
.edge_type = IRQ_TYPE_EDGE_RISING,
.hw_trig = true,
},
{
.name = "external_falling",
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
.edge_type = IRQ_TYPE_EDGE_FALLING,
.hw_trig = true,
},
{
.name = "external_any",
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
.edge_type = IRQ_TYPE_EDGE_BOTH,
.hw_trig = true,
},
{
.name = "software",
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER,
.edge_type = IRQ_TYPE_NONE,
.hw_trig = false,
},
};
@ -597,7 +607,7 @@ static int at91_adc_probe(struct platform_device *pdev)
struct at91_adc_state *st;
struct resource *res;
int ret, i;
u32 edge_type;
u32 edge_type = IRQ_TYPE_NONE;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!indio_dev)
@ -641,14 +651,14 @@ static int at91_adc_probe(struct platform_device *pdev)
ret = of_property_read_u32(pdev->dev.of_node,
"atmel,trigger-edge-type", &edge_type);
if (ret) {
dev_err(&pdev->dev,
"invalid or missing value for atmel,trigger-edge-type\n");
return ret;
dev_dbg(&pdev->dev,
"atmel,trigger-edge-type not specified, only software trigger available\n");
}
st->selected_trig = NULL;
for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
/* find the right trigger, or no trigger at all */
for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT + 1; i++)
if (at91_adc_trigger_list[i].edge_type == edge_type) {
st->selected_trig = &at91_adc_trigger_list[i];
break;
@ -717,24 +727,27 @@ static int at91_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, indio_dev);
ret = at91_adc_buffer_init(indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
goto per_clk_disable_unprepare;
}
if (st->selected_trig->hw_trig) {
ret = at91_adc_buffer_init(indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
goto per_clk_disable_unprepare;
}
ret = at91_adc_trigger_init(indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "couldn't setup the triggers.\n");
goto per_clk_disable_unprepare;
ret = at91_adc_trigger_init(indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "couldn't setup the triggers.\n");
goto per_clk_disable_unprepare;
}
}
ret = iio_device_register(indio_dev);
if (ret < 0)
goto per_clk_disable_unprepare;
dev_info(&pdev->dev, "setting up trigger as %s\n",
st->selected_trig->name);
if (st->selected_trig->hw_trig)
dev_info(&pdev->dev, "setting up trigger as %s\n",
st->selected_trig->name);
dev_info(&pdev->dev, "version: %x\n",
readl_relaxed(st->base + AT91_SAMA5D2_VERSION));

View file

@ -72,6 +72,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
st->event_en = state;
else
return -EINVAL;
break;
default:
return -EINVAL;
}

View file

@ -865,7 +865,6 @@ static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data)
static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev,
struct zpa2326_private *private)
{
int ret;
unsigned int val;
long timeout;
@ -887,14 +886,11 @@ static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev,
/* Timed out. */
zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)",
timeout);
ret = -ETIME;
} else if (timeout < 0) {
zpa2326_warn(indio_dev,
"wait for one shot interrupt cancelled");
ret = -ERESTARTSYS;
return -ETIME;
}
return ret;
zpa2326_warn(indio_dev, "wait for one shot interrupt cancelled");
return -ERESTARTSYS;
}
static int zpa2326_init_managed_irq(struct device *parent,

View file

@ -39,8 +39,12 @@
#define AS3935_AFE_GAIN_MAX 0x1F
#define AS3935_AFE_PWR_BIT BIT(0)
#define AS3935_NFLWDTH 0x01
#define AS3935_NFLWDTH_MASK 0x7f
#define AS3935_INT 0x03
#define AS3935_INT_MASK 0x0f
#define AS3935_DISTURB_INT BIT(2)
#define AS3935_EVENT_INT BIT(3)
#define AS3935_NOISE_INT BIT(0)
@ -48,6 +52,7 @@
#define AS3935_DATA_MASK 0x3F
#define AS3935_TUNE_CAP 0x08
#define AS3935_DEFAULTS 0x3C
#define AS3935_CALIBRATE 0x3D
#define AS3935_READ_DATA BIT(14)
@ -62,7 +67,9 @@ struct as3935_state {
struct mutex lock;
struct delayed_work work;
unsigned long noise_tripped;
u32 tune_cap;
u32 nflwdth_reg;
u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */
u8 buf[2] ____cacheline_aligned;
};
@ -145,12 +152,29 @@ static ssize_t as3935_sensor_sensitivity_store(struct device *dev,
return len;
}
static ssize_t as3935_noise_level_tripped_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct as3935_state *st = iio_priv(dev_to_iio_dev(dev));
int ret;
mutex_lock(&st->lock);
ret = sprintf(buf, "%d\n", !time_after(jiffies, st->noise_tripped + HZ));
mutex_unlock(&st->lock);
return ret;
}
static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0);
static IIO_DEVICE_ATTR(noise_level_tripped, S_IRUGO,
as3935_noise_level_tripped_show, NULL, 0);
static struct attribute *as3935_attributes[] = {
&iio_dev_attr_sensor_sensitivity.dev_attr.attr,
&iio_dev_attr_noise_level_tripped.dev_attr.attr,
NULL,
};
@ -246,7 +270,11 @@ static void as3935_event_work(struct work_struct *work)
case AS3935_EVENT_INT:
iio_trigger_poll_chained(st->trig);
break;
case AS3935_DISTURB_INT:
case AS3935_NOISE_INT:
mutex_lock(&st->lock);
st->noise_tripped = jiffies;
mutex_unlock(&st->lock);
dev_warn(&st->spi->dev, "noise level is too high\n");
break;
}
@ -269,15 +297,14 @@ static irqreturn_t as3935_interrupt_handler(int irq, void *private)
static void calibrate_as3935(struct as3935_state *st)
{
/* mask disturber interrupt bit */
as3935_write(st, AS3935_INT, BIT(5));
as3935_write(st, AS3935_DEFAULTS, 0x96);
as3935_write(st, AS3935_CALIBRATE, 0x96);
as3935_write(st, AS3935_TUNE_CAP,
BIT(5) | (st->tune_cap / TUNE_CAP_DIV));
mdelay(2);
as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
as3935_write(st, AS3935_NFLWDTH, st->nflwdth_reg);
}
#ifdef CONFIG_PM_SLEEP
@ -370,6 +397,15 @@ static int as3935_probe(struct spi_device *spi)
return -EINVAL;
}
ret = of_property_read_u32(np,
"ams,nflwdth", &st->nflwdth_reg);
if (!ret && st->nflwdth_reg > AS3935_NFLWDTH_MASK) {
dev_err(&spi->dev,
"invalid nflwdth setting of %d\n",
st->nflwdth_reg);
return -EINVAL;
}
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->channels = as3935_channels;
@ -384,6 +420,7 @@ static int as3935_probe(struct spi_device *spi)
return -ENOMEM;
st->trig = trig;
st->noise_tripped = jiffies - HZ;
trig->dev.parent = indio_dev->dev.parent;
iio_trigger_set_drvdata(trig, indio_dev);
trig->ops = &iio_interrupt_trigger_ops;

View file

@ -933,58 +933,52 @@ int input_set_keycode(struct input_dev *dev,
}
EXPORT_SYMBOL(input_set_keycode);
bool input_match_device_id(const struct input_dev *dev,
const struct input_device_id *id)
{
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
if (id->bustype != dev->id.bustype)
return false;
if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
if (id->vendor != dev->id.vendor)
return false;
if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
if (id->product != dev->id.product)
return false;
if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
if (id->version != dev->id.version)
return false;
if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX) ||
!bitmap_subset(id->keybit, dev->keybit, KEY_MAX) ||
!bitmap_subset(id->relbit, dev->relbit, REL_MAX) ||
!bitmap_subset(id->absbit, dev->absbit, ABS_MAX) ||
!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX) ||
!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX) ||
!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX) ||
!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX) ||
!bitmap_subset(id->swbit, dev->swbit, SW_MAX) ||
!bitmap_subset(id->propbit, dev->propbit, INPUT_PROP_MAX)) {
return false;
}
return true;
}
EXPORT_SYMBOL(input_match_device_id);
static const struct input_device_id *input_match_device(struct input_handler *handler,
struct input_dev *dev)
{
const struct input_device_id *id;
for (id = handler->id_table; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
if (id->bustype != dev->id.bustype)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
if (id->vendor != dev->id.vendor)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
if (id->product != dev->id.product)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
if (id->version != dev->id.version)
continue;
if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX))
continue;
if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX))
continue;
if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX))
continue;
if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX))
continue;
if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX))
continue;
if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX))
continue;
if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX))
continue;
if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX))
continue;
if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX))
continue;
if (!handler->match || handler->match(handler, dev))
if (input_match_device_id(dev, id) &&
(!handler->match || handler->match(handler, dev))) {
return id;
}
}
return NULL;

View file

@ -747,6 +747,68 @@ static void joydev_cleanup(struct joydev *joydev)
input_close_device(handle);
}
/*
* These codes are copied from from hid-ids.h, unfortunately there is no common
* usb_ids/bt_ids.h header.
*/
#define USB_VENDOR_ID_SONY 0x054c
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER 0x05c4
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0
#define USB_VENDOR_ID_THQ 0x20d6
#define USB_DEVICE_ID_THQ_PS3_UDRAW 0xcb17
#define ACCEL_DEV(vnd, prd) \
{ \
.flags = INPUT_DEVICE_ID_MATCH_VENDOR | \
INPUT_DEVICE_ID_MATCH_PRODUCT | \
INPUT_DEVICE_ID_MATCH_PROPBIT, \
.vendor = (vnd), \
.product = (prd), \
.propbit = { BIT_MASK(INPUT_PROP_ACCELEROMETER) }, \
}
static const struct input_device_id joydev_blacklist[] = {
/* Avoid touchpads and touchscreens */
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
},
/* Avoid tablets, digitisers and similar devices */
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) },
},
/* Disable accelerometers on composite devices */
ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2),
ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE),
ACCEL_DEV(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW),
{ /* sentinel */ }
};
static bool joydev_dev_is_blacklisted(struct input_dev *dev)
{
const struct input_device_id *id;
for (id = joydev_blacklist; id->flags; id++) {
if (input_match_device_id(dev, id)) {
dev_dbg(&dev->dev,
"joydev: blacklisting '%s'\n", dev->name);
return true;
}
}
return false;
}
static bool joydev_dev_is_absolute_mouse(struct input_dev *dev)
{
DECLARE_BITMAP(jd_scratch, KEY_CNT);
@ -807,12 +869,8 @@ static bool joydev_dev_is_absolute_mouse(struct input_dev *dev)
static bool joydev_match(struct input_handler *handler, struct input_dev *dev)
{
/* Avoid touchpads and touchscreens */
if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit))
return false;
/* Avoid tablets, digitisers and similar devices */
if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_DIGI, dev->keybit))
/* Disable blacklisted devices */
if (joydev_dev_is_blacklisted(dev))
return false;
/* Avoid absolute mice */

View file

@ -234,14 +234,7 @@ static irqreturn_t tca8418_irq_handler(int irq, void *dev_id)
static int tca8418_configure(struct tca8418_keypad *keypad_data,
u32 rows, u32 cols)
{
int reg, error;
/* Write config register, if this fails assume device not present */
error = tca8418_write_byte(keypad_data, REG_CFG,
CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN);
if (error < 0)
return -ENODEV;
int reg, error = 0;
/* Assemble a mask for row and column registers */
reg = ~(~0 << rows);
@ -257,6 +250,12 @@ static int tca8418_configure(struct tca8418_keypad *keypad_data,
error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS2, reg >> 8);
error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS3, reg >> 16);
if (error)
return error;
error = tca8418_write_byte(keypad_data, REG_CFG,
CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN);
return error;
}
@ -268,6 +267,7 @@ static int tca8418_keypad_probe(struct i2c_client *client,
struct input_dev *input;
u32 rows = 0, cols = 0;
int error, row_shift, max_keys;
u8 reg;
/* Check i2c driver capabilities */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
@ -301,10 +301,10 @@ static int tca8418_keypad_probe(struct i2c_client *client,
keypad_data->client = client;
keypad_data->row_shift = row_shift;
/* Initialize the chip or fail if chip isn't present */
error = tca8418_configure(keypad_data, rows, cols);
if (error < 0)
return error;
/* Read key lock register, if this fails assume device not present */
error = tca8418_read_byte(keypad_data, REG_KEY_LCK_EC, &reg);
if (error)
return -ENODEV;
/* Configure input device */
input = devm_input_allocate_device(dev);
@ -340,6 +340,11 @@ static int tca8418_keypad_probe(struct i2c_client *client,
return error;
}
/* Initialize the chip */
error = tca8418_configure(keypad_data, rows, cols);
if (error < 0)
return error;
error = input_register_device(input);
if (error) {
dev_err(dev, "Unable to register input device, error: %d\n",

View file

@ -403,6 +403,7 @@ static const struct platform_device_id axp_pek_id_match[] = {
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, axp_pek_id_match);
static struct platform_driver axp20x_pek_driver = {
.probe = axp20x_pek_probe,
@ -417,4 +418,3 @@ module_platform_driver(axp20x_pek_driver);
MODULE_DESCRIPTION("axp20x Power Button");
MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:axp20x-pek");

View file

@ -1635,13 +1635,25 @@ ims_pcu_get_cdc_union_desc(struct usb_interface *intf)
return NULL;
}
while (buflen > 0) {
while (buflen >= sizeof(*union_desc)) {
union_desc = (struct usb_cdc_union_desc *)buf;
if (union_desc->bLength > buflen) {
dev_err(&intf->dev, "Too large descriptor\n");
return NULL;
}
if (union_desc->bDescriptorType == USB_DT_CS_INTERFACE &&
union_desc->bDescriptorSubType == USB_CDC_UNION_TYPE) {
dev_dbg(&intf->dev, "Found union header\n");
return union_desc;
if (union_desc->bLength >= sizeof(*union_desc))
return union_desc;
dev_err(&intf->dev,
"Union descriptor to short (%d vs %zd\n)",
union_desc->bLength, sizeof(*union_desc));
return NULL;
}
buflen -= union_desc->bLength;

View file

@ -1709,8 +1709,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse,
.sensor_pdata = {
.sensor_type = rmi_sensor_touchpad,
.axis_align.flip_y = true,
/* to prevent cursors jumps: */
.kernel_tracking = true,
.kernel_tracking = false,
.topbuttonpad = topbuttonpad,
},
.f30_data = {

View file

@ -72,6 +72,9 @@ struct goodix_ts_data {
#define GOODIX_REG_CONFIG_DATA 0x8047
#define GOODIX_REG_ID 0x8140
#define GOODIX_BUFFER_STATUS_READY BIT(7)
#define GOODIX_BUFFER_STATUS_TIMEOUT 20
#define RESOLUTION_LOC 1
#define MAX_CONTACTS_LOC 5
#define TRIGGER_LOC 6
@ -195,35 +198,53 @@ static int goodix_get_cfg_len(u16 id)
static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
{
unsigned long max_timeout;
int touch_num;
int error;
error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data,
GOODIX_CONTACT_SIZE + 1);
if (error) {
dev_err(&ts->client->dev, "I2C transfer error: %d\n", error);
return error;
}
if (!(data[0] & 0x80))
return -EAGAIN;
touch_num = data[0] & 0x0f;
if (touch_num > ts->max_touch_num)
return -EPROTO;
if (touch_num > 1) {
data += 1 + GOODIX_CONTACT_SIZE;
error = goodix_i2c_read(ts->client,
GOODIX_READ_COOR_ADDR +
1 + GOODIX_CONTACT_SIZE,
data,
GOODIX_CONTACT_SIZE * (touch_num - 1));
if (error)
/*
* The 'buffer status' bit, which indicates that the data is valid, is
* not set as soon as the interrupt is raised, but slightly after.
* This takes around 10 ms to happen, so we poll for 20 ms.
*/
max_timeout = jiffies + msecs_to_jiffies(GOODIX_BUFFER_STATUS_TIMEOUT);
do {
error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR,
data, GOODIX_CONTACT_SIZE + 1);
if (error) {
dev_err(&ts->client->dev, "I2C transfer error: %d\n",
error);
return error;
}
}
return touch_num;
if (data[0] & GOODIX_BUFFER_STATUS_READY) {
touch_num = data[0] & 0x0f;
if (touch_num > ts->max_touch_num)
return -EPROTO;
if (touch_num > 1) {
data += 1 + GOODIX_CONTACT_SIZE;
error = goodix_i2c_read(ts->client,
GOODIX_READ_COOR_ADDR +
1 + GOODIX_CONTACT_SIZE,
data,
GOODIX_CONTACT_SIZE *
(touch_num - 1));
if (error)
return error;
}
return touch_num;
}
usleep_range(1000, 2000); /* Poll every 1 - 2 ms */
} while (time_before(jiffies, max_timeout));
/*
* The Goodix panel will send spurious interrupts after a
* 'finger up' event, which will always cause a timeout.
*/
return 0;
}
static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)

View file

@ -663,12 +663,10 @@ static int stmfts_probe(struct i2c_client *client,
sdata->input->open = stmfts_input_open;
sdata->input->close = stmfts_input_close;
input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_Y);
touchscreen_parse_properties(sdata->input, true, &sdata->prop);
input_set_abs_params(sdata->input, ABS_MT_POSITION_X, 0,
sdata->prop.max_x, 0, 0);
input_set_abs_params(sdata->input, ABS_MT_POSITION_Y, 0,
sdata->prop.max_y, 0, 0);
input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0);

View file

@ -161,7 +161,7 @@ static void titsc_step_config(struct titsc *ts_dev)
break;
case 5:
config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
ts_dev->bit_xn | ts_dev->bit_yp;
STEPCONFIG_XNP | STEPCONFIG_YPN;
break;
case 8:
config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);

View file

@ -107,6 +107,10 @@ struct its_node {
#define ITS_ITT_ALIGN SZ_256
/* The maximum number of VPEID bits supported by VLPI commands */
#define ITS_MAX_VPEID_BITS (16)
#define ITS_MAX_VPEID (1 << (ITS_MAX_VPEID_BITS))
/* Convert page order to size in bytes */
#define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o))
@ -308,7 +312,7 @@ static void its_encode_size(struct its_cmd_block *cmd, u8 size)
static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
{
its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 50, 8);
its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 51, 8);
}
static void its_encode_valid(struct its_cmd_block *cmd, int valid)
@ -318,7 +322,7 @@ static void its_encode_valid(struct its_cmd_block *cmd, int valid)
static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
{
its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 50, 16);
its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 51, 16);
}
static void its_encode_collection(struct its_cmd_block *cmd, u16 col)
@ -358,7 +362,7 @@ static void its_encode_its_list(struct its_cmd_block *cmd, u16 its_list)
static void its_encode_vpt_addr(struct its_cmd_block *cmd, u64 vpt_pa)
{
its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 50, 16);
its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 51, 16);
}
static void its_encode_vpt_size(struct its_cmd_block *cmd, u8 vpt_size)
@ -1478,9 +1482,9 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
u64 val = its_read_baser(its, baser);
u64 esz = GITS_BASER_ENTRY_SIZE(val);
u64 type = GITS_BASER_TYPE(val);
u64 baser_phys, tmp;
u32 alloc_pages;
void *base;
u64 tmp;
retry_alloc_baser:
alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
@ -1496,8 +1500,24 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
if (!base)
return -ENOMEM;
baser_phys = virt_to_phys(base);
/* Check if the physical address of the memory is above 48bits */
if (IS_ENABLED(CONFIG_ARM64_64K_PAGES) && (baser_phys >> 48)) {
/* 52bit PA is supported only when PageSize=64K */
if (psz != SZ_64K) {
pr_err("ITS: no 52bit PA support when psz=%d\n", psz);
free_pages((unsigned long)base, order);
return -ENXIO;
}
/* Convert 52bit PA to 48bit field */
baser_phys = GITS_BASER_PHYS_52_to_48(baser_phys);
}
retry_baser:
val = (virt_to_phys(base) |
val = (baser_phys |
(type << GITS_BASER_TYPE_SHIFT) |
((esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT) |
@ -1582,13 +1602,12 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
static bool its_parse_indirect_baser(struct its_node *its,
struct its_baser *baser,
u32 psz, u32 *order)
u32 psz, u32 *order, u32 ids)
{
u64 tmp = its_read_baser(its, baser);
u64 type = GITS_BASER_TYPE(tmp);
u64 esz = GITS_BASER_ENTRY_SIZE(tmp);
u64 val = GITS_BASER_InnerShareable | GITS_BASER_RaWaWb;
u32 ids = its->device_ids;
u32 new_order = *order;
bool indirect = false;
@ -1680,9 +1699,13 @@ static int its_alloc_tables(struct its_node *its)
continue;
case GITS_BASER_TYPE_DEVICE:
indirect = its_parse_indirect_baser(its, baser,
psz, &order,
its->device_ids);
case GITS_BASER_TYPE_VCPU:
indirect = its_parse_indirect_baser(its, baser,
psz, &order);
psz, &order,
ITS_MAX_VPEID_BITS);
break;
}
@ -2551,7 +2574,7 @@ static struct irq_chip its_vpe_irq_chip = {
static int its_vpe_id_alloc(void)
{
return ida_simple_get(&its_vpeid_ida, 0, 1 << 16, GFP_KERNEL);
return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL);
}
static void its_vpe_id_free(u16 id)
@ -2851,7 +2874,7 @@ static int its_init_vpe_domain(void)
return -ENOMEM;
}
BUG_ON(entries != vpe_proxy.dev->nr_ites);
BUG_ON(entries > vpe_proxy.dev->nr_ites);
raw_spin_lock_init(&vpe_proxy.lock);
vpe_proxy.next_victim = 0;

View file

@ -141,7 +141,7 @@ static void __init tangox_irq_init_chip(struct irq_chip_generic *gc,
for (i = 0; i < 2; i++) {
ct[i].chip.irq_ack = irq_gc_ack_set_bit;
ct[i].chip.irq_mask = irq_gc_mask_disable_reg;
ct[i].chip.irq_mask_ack = irq_gc_mask_disable_reg_and_ack;
ct[i].chip.irq_mask_ack = irq_gc_mask_disable_and_ack_set;
ct[i].chip.irq_unmask = irq_gc_unmask_enable_reg;
ct[i].chip.irq_set_type = tangox_irq_set_type;
ct[i].chip.name = gc->domain->name;

View file

@ -448,6 +448,8 @@ static void intel_dsm_init(struct intel_host *intel_host, struct device *dev,
int err;
u32 val;
intel_host->d3_retune = true;
err = __intel_dsm(intel_host, dev, INTEL_DSM_FNS, &intel_host->dsm_fns);
if (err) {
pr_debug("%s: DSM not supported, error %d\n",

View file

@ -182,22 +182,23 @@
/* FLEXCAN hardware feature flags
*
* Below is some version info we got:
* SOC Version IP-Version Glitch- [TR]WRN_INT Memory err RTR re-
* Filter? connected? detection ception in MB
* MX25 FlexCAN2 03.00.00.00 no no no no
* MX28 FlexCAN2 03.00.04.00 yes yes no no
* MX35 FlexCAN2 03.00.00.00 no no no no
* MX53 FlexCAN2 03.00.00.00 yes no no no
* MX6s FlexCAN3 10.00.12.00 yes yes no yes
* VF610 FlexCAN3 ? no yes yes yes?
* SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR re-
* Filter? connected? Passive detection ception in MB
* MX25 FlexCAN2 03.00.00.00 no no ? no no
* MX28 FlexCAN2 03.00.04.00 yes yes no no no
* MX35 FlexCAN2 03.00.00.00 no no ? no no
* MX53 FlexCAN2 03.00.00.00 yes no no no no
* MX6s FlexCAN3 10.00.12.00 yes yes no no yes
* VF610 FlexCAN3 ? no yes ? yes yes?
*
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
*/
#define FLEXCAN_QUIRK_BROKEN_ERR_STATE BIT(1) /* [TR]WRN_INT not connected */
#define FLEXCAN_QUIRK_BROKEN_WERR_STATE BIT(1) /* [TR]WRN_INT not connected */
#define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2) /* Disable RX FIFO Global mask */
#define FLEXCAN_QUIRK_ENABLE_EACEN_RRS BIT(3) /* Enable EACEN and RRS bit in ctrl2 */
#define FLEXCAN_QUIRK_DISABLE_MECR BIT(4) /* Disable Memory error detection */
#define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5) /* Use timestamp based offloading */
#define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) /* No interrupt for error passive */
/* Structure of the message buffer */
struct flexcan_mb {
@ -281,14 +282,17 @@ struct flexcan_priv {
};
static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE,
.quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE,
};
static const struct flexcan_devtype_data fsl_imx28_devtype_data;
static const struct flexcan_devtype_data fsl_imx28_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE,
};
static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_USE_OFF_TIMESTAMP,
FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE,
};
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
@ -335,6 +339,22 @@ static inline void flexcan_write(u32 val, void __iomem *addr)
}
#endif
static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
{
struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_ctrl = (priv->reg_ctrl_default | FLEXCAN_CTRL_ERR_MSK);
flexcan_write(reg_ctrl, &regs->ctrl);
}
static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv)
{
struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_ctrl = (priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_MSK);
flexcan_write(reg_ctrl, &regs->ctrl);
}
static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
{
if (!priv->reg_xceiver)
@ -713,6 +733,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
struct flexcan_regs __iomem *regs = priv->regs;
irqreturn_t handled = IRQ_NONE;
u32 reg_iflag1, reg_esr;
enum can_state last_state = priv->can.state;
reg_iflag1 = flexcan_read(&regs->iflag1);
@ -765,8 +786,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
}
/* state change interrupt */
if (reg_esr & FLEXCAN_ESR_ERR_STATE)
/* state change interrupt or broken error state quirk fix is enabled */
if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
(priv->devtype_data->quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
flexcan_irq_state(dev, reg_esr);
/* bus error IRQ - handle if bus error reporting is activated */
@ -774,6 +797,44 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
flexcan_irq_bus_err(dev, reg_esr);
/* availability of error interrupt among state transitions in case
* bus error reporting is de-activated and
* FLEXCAN_QUIRK_BROKEN_PERR_STATE is enabled:
* +--------------------------------------------------------------+
* | +----------------------------------------------+ [stopped / |
* | | | sleeping] -+
* +-+-> active <-> warning <-> passive -> bus off -+
* ___________^^^^^^^^^^^^_______________________________
* disabled(1) enabled disabled
*
* (1): enabled if FLEXCAN_QUIRK_BROKEN_WERR_STATE is enabled
*/
if ((last_state != priv->can.state) &&
(priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE) &&
!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) {
switch (priv->can.state) {
case CAN_STATE_ERROR_ACTIVE:
if (priv->devtype_data->quirks &
FLEXCAN_QUIRK_BROKEN_WERR_STATE)
flexcan_error_irq_enable(priv);
else
flexcan_error_irq_disable(priv);
break;
case CAN_STATE_ERROR_WARNING:
flexcan_error_irq_enable(priv);
break;
case CAN_STATE_ERROR_PASSIVE:
case CAN_STATE_BUS_OFF:
flexcan_error_irq_disable(priv);
break;
default:
break;
}
}
return handled;
}
@ -887,7 +948,7 @@ static int flexcan_chip_start(struct net_device *dev)
* on most Flexcan cores, too. Otherwise we don't get
* any error warning or passive interrupts.
*/
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_ERR_STATE ||
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE ||
priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
else

View file

@ -333,7 +333,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv,
}
cf->can_id = id & ESD_IDMASK;
cf->can_dlc = get_can_dlc(msg->msg.rx.dlc);
cf->can_dlc = get_can_dlc(msg->msg.rx.dlc & ~ESD_RTR);
if (id & ESD_EXTID)
cf->can_id |= CAN_EFF_FLAG;

View file

@ -375,6 +375,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
gs_free_tx_context(txc);
atomic_dec(&dev->active_tx_urbs);
netif_wake_queue(netdev);
}
@ -463,14 +465,6 @@ static void gs_usb_xmit_callback(struct urb *urb)
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
atomic_dec(&dev->active_tx_urbs);
if (!netif_device_present(netdev))
return;
if (netif_queue_stopped(netdev))
netif_wake_queue(netdev);
}
static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,

View file

@ -214,8 +214,14 @@ static int mv88e6060_setup(struct dsa_switch *ds)
static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr)
{
/* Use the same MAC Address as FD Pause frames for all ports */
REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 9) | addr[1]);
u16 val = addr[0] << 8 | addr[1];
/* The multicast bit is always transmitted as a zero, so the switch uses
* bit 8 for "DiffAddr", where 0 means all ports transmit the same SA.
*/
val &= 0xfeff;
REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, val);
REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]);
REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]);

View file

@ -742,8 +742,8 @@ static void ena_get_channels(struct net_device *netdev,
{
struct ena_adapter *adapter = netdev_priv(netdev);
channels->max_rx = ENA_MAX_NUM_IO_QUEUES;
channels->max_tx = ENA_MAX_NUM_IO_QUEUES;
channels->max_rx = adapter->num_queues;
channels->max_tx = adapter->num_queues;
channels->max_other = 0;
channels->max_combined = 0;
channels->rx_count = adapter->num_queues;

View file

@ -966,7 +966,7 @@ static inline void ena_rx_checksum(struct ena_ring *rx_ring,
u64_stats_update_begin(&rx_ring->syncp);
rx_ring->rx_stats.bad_csum++;
u64_stats_update_end(&rx_ring->syncp);
netif_err(rx_ring->adapter, rx_err, rx_ring->netdev,
netif_dbg(rx_ring->adapter, rx_err, rx_ring->netdev,
"RX IPv4 header checksum error\n");
return;
}
@ -979,7 +979,7 @@ static inline void ena_rx_checksum(struct ena_ring *rx_ring,
u64_stats_update_begin(&rx_ring->syncp);
rx_ring->rx_stats.bad_csum++;
u64_stats_update_end(&rx_ring->syncp);
netif_err(rx_ring->adapter, rx_err, rx_ring->netdev,
netif_dbg(rx_ring->adapter, rx_err, rx_ring->netdev,
"RX L4 checksum error\n");
skb->ip_summed = CHECKSUM_NONE;
return;
@ -3064,7 +3064,8 @@ static void ena_release_bars(struct ena_com_dev *ena_dev, struct pci_dev *pdev)
if (ena_dev->mem_bar)
devm_iounmap(&pdev->dev, ena_dev->mem_bar);
devm_iounmap(&pdev->dev, ena_dev->reg_bar);
if (ena_dev->reg_bar)
devm_iounmap(&pdev->dev, ena_dev->reg_bar);
release_bars = pci_select_bars(pdev, IORESOURCE_MEM) & ENA_BAR_MASK;
pci_release_selected_regions(pdev, release_bars);

View file

@ -22,8 +22,12 @@
#define AQ_CFG_FORCE_LEGACY_INT 0U
#define AQ_CFG_IS_INTERRUPT_MODERATION_DEF 1U
#define AQ_CFG_INTERRUPT_MODERATION_RATE_DEF 0xFFFFU
#define AQ_CFG_INTERRUPT_MODERATION_OFF 0
#define AQ_CFG_INTERRUPT_MODERATION_ON 1
#define AQ_CFG_INTERRUPT_MODERATION_AUTO 0xFFFFU
#define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2)
#define AQ_CFG_IRQ_MASK 0x1FFU
#define AQ_CFG_VECS_MAX 8U

View file

@ -56,10 +56,6 @@ aq_ethtool_set_link_ksettings(struct net_device *ndev,
return aq_nic_set_link_ksettings(aq_nic, cmd);
}
/* there "5U" is number of queue[#] stats lines (InPackets+...+InErrors) */
static const unsigned int aq_ethtool_stat_queue_lines = 5U;
static const unsigned int aq_ethtool_stat_queue_chars =
5U * ETH_GSTRING_LEN;
static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
"InPackets",
"InUCast",
@ -83,56 +79,26 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
"InOctetsDma",
"OutOctetsDma",
"InDroppedDma",
"Queue[0] InPackets",
"Queue[0] OutPackets",
"Queue[0] InJumboPackets",
"Queue[0] InLroPackets",
"Queue[0] InErrors",
"Queue[1] InPackets",
"Queue[1] OutPackets",
"Queue[1] InJumboPackets",
"Queue[1] InLroPackets",
"Queue[1] InErrors",
"Queue[2] InPackets",
"Queue[2] OutPackets",
"Queue[2] InJumboPackets",
"Queue[2] InLroPackets",
"Queue[2] InErrors",
"Queue[3] InPackets",
"Queue[3] OutPackets",
"Queue[3] InJumboPackets",
"Queue[3] InLroPackets",
"Queue[3] InErrors",
"Queue[4] InPackets",
"Queue[4] OutPackets",
"Queue[4] InJumboPackets",
"Queue[4] InLroPackets",
"Queue[4] InErrors",
"Queue[5] InPackets",
"Queue[5] OutPackets",
"Queue[5] InJumboPackets",
"Queue[5] InLroPackets",
"Queue[5] InErrors",
"Queue[6] InPackets",
"Queue[6] OutPackets",
"Queue[6] InJumboPackets",
"Queue[6] InLroPackets",
"Queue[6] InErrors",
"Queue[7] InPackets",
"Queue[7] OutPackets",
"Queue[7] InJumboPackets",
"Queue[7] InLroPackets",
"Queue[7] InErrors",
};
static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
"Queue[%d] InPackets",
"Queue[%d] OutPackets",
"Queue[%d] Restarts",
"Queue[%d] InJumboPackets",
"Queue[%d] InLroPackets",
"Queue[%d] InErrors",
};
static void aq_ethtool_stats(struct net_device *ndev,
struct ethtool_stats *stats, u64 *data)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
/* ASSERT: Need add lines to aq_ethtool_stat_names if AQ_CFG_VECS_MAX > 8 */
BUILD_BUG_ON(AQ_CFG_VECS_MAX > 8);
memset(data, 0, ARRAY_SIZE(aq_ethtool_stat_names) * sizeof(u64));
memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) +
ARRAY_SIZE(aq_ethtool_queue_stat_names) *
cfg->vecs) * sizeof(u64));
aq_nic_get_stats(aq_nic, data);
}
@ -154,8 +120,8 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
sizeof(drvinfo->bus_info));
drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) -
(AQ_CFG_VECS_MAX - cfg->vecs) * aq_ethtool_stat_queue_lines;
drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
drvinfo->testinfo_len = 0;
drvinfo->regdump_len = regs_count;
drvinfo->eedump_len = 0;
@ -164,14 +130,25 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
static void aq_ethtool_get_strings(struct net_device *ndev,
u32 stringset, u8 *data)
{
int i, si;
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
u8 *p = data;
if (stringset == ETH_SS_STATS)
memcpy(data, *aq_ethtool_stat_names,
sizeof(aq_ethtool_stat_names) -
(AQ_CFG_VECS_MAX - cfg->vecs) *
aq_ethtool_stat_queue_chars);
if (stringset == ETH_SS_STATS) {
memcpy(p, *aq_ethtool_stat_names,
sizeof(aq_ethtool_stat_names));
p = p + sizeof(aq_ethtool_stat_names);
for (i = 0; i < cfg->vecs; i++) {
for (si = 0;
si < ARRAY_SIZE(aq_ethtool_queue_stat_names);
si++) {
snprintf(p, ETH_GSTRING_LEN,
aq_ethtool_queue_stat_names[si], i);
p += ETH_GSTRING_LEN;
}
}
}
}
static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
@ -182,9 +159,8 @@ static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
switch (stringset) {
case ETH_SS_STATS:
ret = ARRAY_SIZE(aq_ethtool_stat_names) -
(AQ_CFG_VECS_MAX - cfg->vecs) *
aq_ethtool_stat_queue_lines;
ret = ARRAY_SIZE(aq_ethtool_stat_names) +
cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
break;
default:
ret = -EOPNOTSUPP;
@ -245,6 +221,69 @@ static int aq_ethtool_get_rxnfc(struct net_device *ndev,
return err;
}
int aq_ethtool_get_coalesce(struct net_device *ndev,
struct ethtool_coalesce *coal)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
coal->rx_coalesce_usecs = cfg->rx_itr;
coal->tx_coalesce_usecs = cfg->tx_itr;
coal->rx_max_coalesced_frames = 0;
coal->tx_max_coalesced_frames = 0;
} else {
coal->rx_coalesce_usecs = 0;
coal->tx_coalesce_usecs = 0;
coal->rx_max_coalesced_frames = 1;
coal->tx_max_coalesced_frames = 1;
}
return 0;
}
int aq_ethtool_set_coalesce(struct net_device *ndev,
struct ethtool_coalesce *coal)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
/* This is not yet supported
*/
if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce)
return -EOPNOTSUPP;
/* Atlantic only supports timing based coalescing
*/
if (coal->rx_max_coalesced_frames > 1 ||
coal->rx_coalesce_usecs_irq ||
coal->rx_max_coalesced_frames_irq)
return -EOPNOTSUPP;
if (coal->tx_max_coalesced_frames > 1 ||
coal->tx_coalesce_usecs_irq ||
coal->tx_max_coalesced_frames_irq)
return -EOPNOTSUPP;
/* We do not support frame counting. Check this
*/
if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
return -EOPNOTSUPP;
if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
return -EOPNOTSUPP;
if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
return -EINVAL;
cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
cfg->rx_itr = coal->rx_coalesce_usecs;
cfg->tx_itr = coal->tx_coalesce_usecs;
return aq_nic_update_interrupt_moderation_settings(aq_nic);
}
const struct ethtool_ops aq_ethtool_ops = {
.get_link = aq_ethtool_get_link,
.get_regs_len = aq_ethtool_get_regs_len,
@ -259,4 +298,6 @@ const struct ethtool_ops aq_ethtool_ops = {
.get_ethtool_stats = aq_ethtool_stats,
.get_link_ksettings = aq_ethtool_get_link_ksettings,
.set_link_ksettings = aq_ethtool_set_link_ksettings,
.get_coalesce = aq_ethtool_get_coalesce,
.set_coalesce = aq_ethtool_set_coalesce,
};

View file

@ -151,8 +151,7 @@ struct aq_hw_ops {
[ETH_ALEN],
u32 count);
int (*hw_interrupt_moderation_set)(struct aq_hw_s *self,
bool itr_enabled);
int (*hw_interrupt_moderation_set)(struct aq_hw_s *self);
int (*hw_rss_set)(struct aq_hw_s *self,
struct aq_rss_parameters *rss_params);
@ -163,6 +162,8 @@ struct aq_hw_ops {
int (*hw_get_regs)(struct aq_hw_s *self,
struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff);
int (*hw_update_stats)(struct aq_hw_s *self);
int (*hw_get_hw_stats)(struct aq_hw_s *self, u64 *data,
unsigned int *p_count);

View file

@ -16,6 +16,7 @@
#include "aq_pci_func.h"
#include "aq_nic_internal.h"
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/timer.h>
@ -24,6 +25,18 @@
#include <linux/tcp.h>
#include <net/ip.h>
static unsigned int aq_itr = AQ_CFG_INTERRUPT_MODERATION_AUTO;
module_param_named(aq_itr, aq_itr, uint, 0644);
MODULE_PARM_DESC(aq_itr, "Interrupt throttling mode");
static unsigned int aq_itr_tx;
module_param_named(aq_itr_tx, aq_itr_tx, uint, 0644);
MODULE_PARM_DESC(aq_itr_tx, "TX interrupt throttle rate");
static unsigned int aq_itr_rx;
module_param_named(aq_itr_rx, aq_itr_rx, uint, 0644);
MODULE_PARM_DESC(aq_itr_rx, "RX interrupt throttle rate");
static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues)
{
struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
@ -61,9 +74,9 @@ static void aq_nic_cfg_init_defaults(struct aq_nic_s *self)
cfg->is_polling = AQ_CFG_IS_POLLING_DEF;
cfg->is_interrupt_moderation = AQ_CFG_IS_INTERRUPT_MODERATION_DEF;
cfg->itr = cfg->is_interrupt_moderation ?
AQ_CFG_INTERRUPT_MODERATION_RATE_DEF : 0U;
cfg->itr = aq_itr;
cfg->tx_itr = aq_itr_tx;
cfg->rx_itr = aq_itr_rx;
cfg->is_rss = AQ_CFG_IS_RSS_DEF;
cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF;
@ -126,10 +139,12 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
if (err)
return err;
if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps)
if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps) {
pr_info("%s: link change old %d new %d\n",
AQ_CFG_DRV_NAME, self->link_status.mbps,
self->aq_hw->aq_link_status.mbps);
aq_nic_update_interrupt_moderation_settings(self);
}
self->link_status = self->aq_hw->aq_link_status;
if (!netif_carrier_ok(self->ndev) && self->link_status.mbps) {
@ -164,8 +179,8 @@ static void aq_nic_service_timer_cb(unsigned long param)
if (err)
goto err_exit;
self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
self->aq_nic_cfg.is_interrupt_moderation);
if (self->aq_hw_ops.hw_update_stats)
self->aq_hw_ops.hw_update_stats(self->aq_hw);
memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
@ -334,6 +349,7 @@ struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev)
}
if (netif_running(ndev))
netif_tx_disable(ndev);
netif_carrier_off(self->ndev);
for (self->aq_vecs = 0; self->aq_vecs < self->aq_nic_cfg.vecs;
self->aq_vecs++) {
@ -421,9 +437,8 @@ int aq_nic_start(struct aq_nic_s *self)
if (err < 0)
goto err_exit;
err = self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
self->aq_nic_cfg.is_interrupt_moderation);
if (err < 0)
err = aq_nic_update_interrupt_moderation_settings(self);
if (err)
goto err_exit;
setup_timer(&self->service_timer, &aq_nic_service_timer_cb,
(unsigned long)self);
@ -645,6 +660,11 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
return err;
}
int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self)
{
return self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw);
}
int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags)
{
int err = 0;
@ -899,6 +919,7 @@ int aq_nic_stop(struct aq_nic_s *self)
unsigned int i = 0U;
netif_tx_disable(self->ndev);
netif_carrier_off(self->ndev);
del_timer_sync(&self->service_timer);

View file

@ -40,6 +40,8 @@ struct aq_nic_cfg_s {
u32 vecs; /* vecs==allocated irqs */
u32 irq_type;
u32 itr;
u16 rx_itr;
u16 tx_itr;
u32 num_rss_queues;
u32 mtu;
u32 ucp_0x364;
@ -49,7 +51,6 @@ struct aq_nic_cfg_s {
u16 is_mc_list_enabled;
u16 mc_list_count;
bool is_autoneg;
bool is_interrupt_moderation;
bool is_polling;
bool is_rss;
bool is_lro;
@ -104,5 +105,6 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self,
struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self);
u32 aq_nic_get_fw_version(struct aq_nic_s *self);
int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg);
int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self);
#endif /* AQ_NIC_H */

View file

@ -85,6 +85,7 @@ int aq_pci_func_init(struct aq_pci_func_s *self)
int err = 0;
unsigned int bar = 0U;
unsigned int port = 0U;
unsigned int numvecs = 0U;
err = pci_enable_device(self->pdev);
if (err < 0)
@ -142,10 +143,12 @@ int aq_pci_func_init(struct aq_pci_func_s *self)
}
}
/*enable interrupts */
numvecs = min((u8)AQ_CFG_VECS_DEF, self->aq_hw_caps.msix_irqs);
numvecs = min(numvecs, num_online_cpus());
/* enable interrupts */
#if !AQ_CFG_FORCE_LEGACY_INT
err = pci_alloc_irq_vectors(self->pdev, self->aq_hw_caps.msix_irqs,
self->aq_hw_caps.msix_irqs, PCI_IRQ_MSIX);
err = pci_alloc_irq_vectors(self->pdev, numvecs, numvecs, PCI_IRQ_MSIX);
if (err < 0) {
err = pci_alloc_irq_vectors(self->pdev, 1, 1,
@ -153,7 +156,7 @@ int aq_pci_func_init(struct aq_pci_func_s *self)
if (err < 0)
goto err_exit;
}
#endif
#endif /* AQ_CFG_FORCE_LEGACY_INT */
/* net device init */
for (port = 0; port < self->ports; ++port) {
@ -265,6 +268,9 @@ void aq_pci_func_free(struct aq_pci_func_s *self)
aq_nic_ndev_free(self->port[port]);
}
if (self->mmio)
iounmap(self->mmio);
kfree(self);
err_exit:;

View file

@ -373,8 +373,11 @@ int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count)
memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
aq_vec_add_stats(self, &stats_rx, &stats_tx);
/* This data should mimic aq_ethtool_queue_stat_names structure
*/
data[count] += stats_rx.packets;
data[++count] += stats_tx.packets;
data[++count] += stats_tx.queue_restarts;
data[++count] += stats_rx.jumbo_packets;
data[++count] += stats_rx.lro_packets;
data[++count] += stats_rx.errors;

View file

@ -765,24 +765,23 @@ static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self,
return err;
}
static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self,
bool itr_enabled)
static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self)
{
unsigned int i = 0U;
u32 itr_rx;
if (itr_enabled && self->aq_nic_cfg->itr) {
if (self->aq_nic_cfg->itr != 0xFFFFU) {
if (self->aq_nic_cfg->itr) {
if (self->aq_nic_cfg->itr != AQ_CFG_INTERRUPT_MODERATION_AUTO) {
u32 itr_ = (self->aq_nic_cfg->itr >> 1);
itr_ = min(AQ_CFG_IRQ_MASK, itr_);
PHAL_ATLANTIC_A0->itr_rx = 0x80000000U |
(itr_ << 0x10);
itr_rx = 0x80000000U | (itr_ << 0x10);
} else {
u32 n = 0xFFFFU & aq_hw_read_reg(self, 0x00002A00U);
if (n < self->aq_link_status.mbps) {
PHAL_ATLANTIC_A0->itr_rx = 0U;
itr_rx = 0U;
} else {
static unsigned int hw_timers_tbl_[] = {
0x01CU, /* 10Gbit */
@ -797,8 +796,7 @@ static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self,
hw_atl_utils_mbps_2_speed_index(
self->aq_link_status.mbps);
PHAL_ATLANTIC_A0->itr_rx =
0x80000000U |
itr_rx = 0x80000000U |
(hw_timers_tbl_[speed_index] << 0x10U);
}
@ -806,11 +804,11 @@ static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self,
aq_hw_write_reg(self, 0x00002A00U, 0x8D000000U);
}
} else {
PHAL_ATLANTIC_A0->itr_rx = 0U;
itr_rx = 0U;
}
for (i = HW_ATL_A0_RINGS_MAX; i--;)
reg_irq_thr_set(self, PHAL_ATLANTIC_A0->itr_rx, i);
reg_irq_thr_set(self, itr_rx, i);
return aq_hw_err_from_flags(self);
}
@ -885,6 +883,7 @@ static struct aq_hw_ops hw_atl_ops_ = {
.hw_rss_set = hw_atl_a0_hw_rss_set,
.hw_rss_hash_set = hw_atl_a0_hw_rss_hash_set,
.hw_get_regs = hw_atl_utils_hw_get_regs,
.hw_update_stats = hw_atl_utils_update_stats,
.hw_get_hw_stats = hw_atl_utils_get_hw_stats,
.hw_get_fw_version = hw_atl_utils_get_fw_version,
};

View file

@ -788,39 +788,45 @@ static int hw_atl_b0_hw_multicast_list_set(struct aq_hw_s *self,
return err;
}
static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self,
bool itr_enabled)
static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self)
{
unsigned int i = 0U;
u32 itr_tx = 2U;
u32 itr_rx = 2U;
if (itr_enabled && self->aq_nic_cfg->itr) {
switch (self->aq_nic_cfg->itr) {
case AQ_CFG_INTERRUPT_MODERATION_ON:
case AQ_CFG_INTERRUPT_MODERATION_AUTO:
tdm_tx_desc_wr_wb_irq_en_set(self, 0U);
tdm_tdm_intr_moder_en_set(self, 1U);
rdm_rx_desc_wr_wb_irq_en_set(self, 0U);
rdm_rdm_intr_moder_en_set(self, 1U);
PHAL_ATLANTIC_B0->itr_tx = 2U;
PHAL_ATLANTIC_B0->itr_rx = 2U;
if (self->aq_nic_cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON) {
/* HW timers are in 2us units */
int tx_max_timer = self->aq_nic_cfg->tx_itr / 2;
int tx_min_timer = tx_max_timer / 2;
if (self->aq_nic_cfg->itr != 0xFFFFU) {
unsigned int max_timer = self->aq_nic_cfg->itr / 2U;
unsigned int min_timer = self->aq_nic_cfg->itr / 32U;
int rx_max_timer = self->aq_nic_cfg->rx_itr / 2;
int rx_min_timer = rx_max_timer / 2;
max_timer = min(0x1FFU, max_timer);
min_timer = min(0xFFU, min_timer);
tx_max_timer = min(HW_ATL_INTR_MODER_MAX, tx_max_timer);
tx_min_timer = min(HW_ATL_INTR_MODER_MIN, tx_min_timer);
rx_max_timer = min(HW_ATL_INTR_MODER_MAX, rx_max_timer);
rx_min_timer = min(HW_ATL_INTR_MODER_MIN, rx_min_timer);
PHAL_ATLANTIC_B0->itr_tx |= min_timer << 0x8U;
PHAL_ATLANTIC_B0->itr_tx |= max_timer << 0x10U;
PHAL_ATLANTIC_B0->itr_rx |= min_timer << 0x8U;
PHAL_ATLANTIC_B0->itr_rx |= max_timer << 0x10U;
itr_tx |= tx_min_timer << 0x8U;
itr_tx |= tx_max_timer << 0x10U;
itr_rx |= rx_min_timer << 0x8U;
itr_rx |= rx_max_timer << 0x10U;
} else {
static unsigned int hw_atl_b0_timers_table_tx_[][2] = {
{0xffU, 0xffU}, /* 10Gbit */
{0xffU, 0x1ffU}, /* 5Gbit */
{0xffU, 0x1ffU}, /* 5Gbit 5GS */
{0xffU, 0x1ffU}, /* 2.5Gbit */
{0xffU, 0x1ffU}, /* 1Gbit */
{0xffU, 0x1ffU}, /* 100Mbit */
{0xfU, 0xffU}, /* 10Gbit */
{0xfU, 0x1ffU}, /* 5Gbit */
{0xfU, 0x1ffU}, /* 5Gbit 5GS */
{0xfU, 0x1ffU}, /* 2.5Gbit */
{0xfU, 0x1ffU}, /* 1Gbit */
{0xfU, 0x1ffU}, /* 100Mbit */
};
static unsigned int hw_atl_b0_timers_table_rx_[][2] = {
@ -836,34 +842,36 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self,
hw_atl_utils_mbps_2_speed_index(
self->aq_link_status.mbps);
PHAL_ATLANTIC_B0->itr_tx |=
hw_atl_b0_timers_table_tx_[speed_index]
[0] << 0x8U; /* set min timer value */
PHAL_ATLANTIC_B0->itr_tx |=
hw_atl_b0_timers_table_tx_[speed_index]
[1] << 0x10U; /* set max timer value */
/* Update user visible ITR settings */
self->aq_nic_cfg->tx_itr = hw_atl_b0_timers_table_tx_
[speed_index][1] * 2;
self->aq_nic_cfg->rx_itr = hw_atl_b0_timers_table_rx_
[speed_index][1] * 2;
PHAL_ATLANTIC_B0->itr_rx |=
hw_atl_b0_timers_table_rx_[speed_index]
[0] << 0x8U; /* set min timer value */
PHAL_ATLANTIC_B0->itr_rx |=
hw_atl_b0_timers_table_rx_[speed_index]
[1] << 0x10U; /* set max timer value */
itr_tx |= hw_atl_b0_timers_table_tx_
[speed_index][0] << 0x8U;
itr_tx |= hw_atl_b0_timers_table_tx_
[speed_index][1] << 0x10U;
itr_rx |= hw_atl_b0_timers_table_rx_
[speed_index][0] << 0x8U;
itr_rx |= hw_atl_b0_timers_table_rx_
[speed_index][1] << 0x10U;
}
} else {
break;
case AQ_CFG_INTERRUPT_MODERATION_OFF:
tdm_tx_desc_wr_wb_irq_en_set(self, 1U);
tdm_tdm_intr_moder_en_set(self, 0U);
rdm_rx_desc_wr_wb_irq_en_set(self, 1U);
rdm_rdm_intr_moder_en_set(self, 0U);
PHAL_ATLANTIC_B0->itr_tx = 0U;
PHAL_ATLANTIC_B0->itr_rx = 0U;
itr_tx = 0U;
itr_rx = 0U;
break;
}
for (i = HW_ATL_B0_RINGS_MAX; i--;) {
reg_tx_intr_moder_ctrl_set(self,
PHAL_ATLANTIC_B0->itr_tx, i);
reg_rx_intr_moder_ctrl_set(self,
PHAL_ATLANTIC_B0->itr_rx, i);
reg_tx_intr_moder_ctrl_set(self, itr_tx, i);
reg_rx_intr_moder_ctrl_set(self, itr_rx, i);
}
return aq_hw_err_from_flags(self);
@ -939,6 +947,7 @@ static struct aq_hw_ops hw_atl_ops_ = {
.hw_rss_set = hw_atl_b0_hw_rss_set,
.hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set,
.hw_get_regs = hw_atl_utils_hw_get_regs,
.hw_update_stats = hw_atl_utils_update_stats,
.hw_get_hw_stats = hw_atl_utils_get_hw_stats,
.hw_get_fw_version = hw_atl_utils_get_fw_version,
};

View file

@ -139,6 +139,9 @@
#define HW_ATL_B0_FW_VER_EXPECTED 0x01050006U
#define HW_ATL_INTR_MODER_MAX 0x1FF
#define HW_ATL_INTR_MODER_MIN 0xFF
/* Hardware tx descriptor */
struct __packed hw_atl_txd_s {
u64 buf_addr;

View file

@ -255,6 +255,15 @@ static int hw_atl_utils_mpi_create(struct aq_hw_s *self,
return err;
}
int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
struct hw_aq_atl_utils_mbox_header *pmbox)
{
return hw_atl_utils_fw_downld_dwords(self,
PHAL_ATLANTIC->mbox_addr,
(u32 *)(void *)pmbox,
sizeof(*pmbox) / sizeof(u32));
}
void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
struct hw_aq_atl_utils_mbox *pmbox)
{
@ -267,9 +276,6 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
if (err < 0)
goto err_exit;
if (pmbox != &PHAL_ATLANTIC->mbox)
memcpy(pmbox, &PHAL_ATLANTIC->mbox, sizeof(*pmbox));
if (IS_CHIP_FEATURE(REVISION_A0)) {
unsigned int mtu = self->aq_nic_cfg ?
self->aq_nic_cfg->mtu : 1514U;
@ -299,17 +305,17 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self,
{
int err = 0;
u32 transaction_id = 0;
struct hw_aq_atl_utils_mbox_header mbox;
if (state == MPI_RESET) {
hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
hw_atl_utils_mpi_read_mbox(self, &mbox);
transaction_id = PHAL_ATLANTIC->mbox.transaction_id;
transaction_id = mbox.transaction_id;
AQ_HW_WAIT_FOR(transaction_id !=
(hw_atl_utils_mpi_read_stats
(self, &PHAL_ATLANTIC->mbox),
PHAL_ATLANTIC->mbox.transaction_id),
1000U, 100U);
(hw_atl_utils_mpi_read_mbox(self, &mbox),
mbox.transaction_id),
1000U, 100U);
if (err < 0)
goto err_exit;
}
@ -492,16 +498,51 @@ int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
return 0;
}
int hw_atl_utils_update_stats(struct aq_hw_s *self)
{
struct hw_atl_s *hw_self = PHAL_ATLANTIC;
struct hw_aq_atl_utils_mbox mbox;
if (!self->aq_link_status.mbps)
return 0;
hw_atl_utils_mpi_read_stats(self, &mbox);
#define AQ_SDELTA(_N_) (hw_self->curr_stats._N_ += \
mbox.stats._N_ - hw_self->last_stats._N_)
AQ_SDELTA(uprc);
AQ_SDELTA(mprc);
AQ_SDELTA(bprc);
AQ_SDELTA(erpt);
AQ_SDELTA(uptc);
AQ_SDELTA(mptc);
AQ_SDELTA(bptc);
AQ_SDELTA(erpr);
AQ_SDELTA(ubrc);
AQ_SDELTA(ubtc);
AQ_SDELTA(mbrc);
AQ_SDELTA(mbtc);
AQ_SDELTA(bbrc);
AQ_SDELTA(bbtc);
AQ_SDELTA(dpc);
#undef AQ_SDELTA
memcpy(&hw_self->last_stats, &mbox.stats, sizeof(mbox.stats));
return 0;
}
int hw_atl_utils_get_hw_stats(struct aq_hw_s *self,
u64 *data, unsigned int *p_count)
{
struct hw_atl_stats_s *stats = NULL;
struct hw_atl_s *hw_self = PHAL_ATLANTIC;
struct hw_atl_stats_s *stats = &hw_self->curr_stats;
int i = 0;
hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
stats = &PHAL_ATLANTIC->mbox.stats;
data[i] = stats->uprc + stats->mprc + stats->bprc;
data[++i] = stats->uprc;
data[++i] = stats->mprc;

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