mirror of
https://github.com/Qortal/Brooklyn.git
synced 2025-02-11 17:55:54 +00:00
Source update
Lot of goodies there.
This commit is contained in:
parent
80d353169d
commit
631d643d50
@ -105,9 +105,13 @@ &fec {
|
|||||||
phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
|
phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
|
||||||
phy-reset-duration = <20>;
|
phy-reset-duration = <20>;
|
||||||
phy-supply = <&sw2_reg>;
|
phy-supply = <&sw2_reg>;
|
||||||
phy-handle = <ðphy0>;
|
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
|
fixed-link {
|
||||||
|
speed = <1000>;
|
||||||
|
full-duplex;
|
||||||
|
};
|
||||||
|
|
||||||
mdio {
|
mdio {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
@ -406,6 +406,18 @@ ®_soc {
|
|||||||
vin-supply = <&sw1_reg>;
|
vin-supply = <&sw1_reg>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
®_pu {
|
||||||
|
vin-supply = <&sw1_reg>;
|
||||||
|
};
|
||||||
|
|
||||||
|
®_vdd1p1 {
|
||||||
|
vin-supply = <&sw2_reg>;
|
||||||
|
};
|
||||||
|
|
||||||
|
®_vdd2p5 {
|
||||||
|
vin-supply = <&sw2_reg>;
|
||||||
|
};
|
||||||
|
|
||||||
&uart1 {
|
&uart1 {
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&pinctrl_uart1>;
|
pinctrl-0 = <&pinctrl_uart1>;
|
||||||
|
@ -193,7 +193,7 @@ &usdhc1 {
|
|||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&pinctrl_usdhc1>;
|
pinctrl-0 = <&pinctrl_usdhc1>;
|
||||||
keep-power-in-suspend;
|
keep-power-in-suspend;
|
||||||
tuning-step = <2>;
|
fsl,tuning-step = <2>;
|
||||||
vmmc-supply = <®_3p3v>;
|
vmmc-supply = <®_3p3v>;
|
||||||
no-1-8-v;
|
no-1-8-v;
|
||||||
broken-cd;
|
broken-cd;
|
||||||
|
@ -351,7 +351,7 @@ &usdhc1 {
|
|||||||
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
|
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
|
||||||
cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
tuning-step = <2>;
|
fsl,tuning-step = <2>;
|
||||||
vmmc-supply = <®_3p3v>;
|
vmmc-supply = <®_3p3v>;
|
||||||
wakeup-source;
|
wakeup-source;
|
||||||
no-1-8-v;
|
no-1-8-v;
|
||||||
|
@ -82,14 +82,20 @@ amp_off {
|
|||||||
|
|
||||||
amp_on_1 {
|
amp_on_1 {
|
||||||
set = <RELAY1 1>;
|
set = <RELAY1 1>;
|
||||||
amp_on = <GF_DELAY 1000>;
|
amp_on_2 = <GF_DELAY 1000>;
|
||||||
amp_off = <ENABLE 0>;
|
amp_off = <GF_SHUTDOWN 0>;
|
||||||
|
fault = <FAULT 1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
amp_on_2 {
|
||||||
|
set = <RELAY2 1>;
|
||||||
|
amp_on_wait = <ENABLE 0>;
|
||||||
|
amp_on = <GF_DELAY 1>;
|
||||||
fault = <FAULT 1>;
|
fault = <FAULT 1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
amp_on {
|
amp_on {
|
||||||
set = <RELAY2 1>,
|
set = <RELAYSSR 1>;
|
||||||
<RELAYSSR 1>;
|
|
||||||
amp_on_wait = <ENABLE 0>;
|
amp_on_wait = <ENABLE 0>;
|
||||||
fault = <FAULT 1>;
|
fault = <FAULT 1>;
|
||||||
};
|
};
|
||||||
|
@ -320,7 +320,7 @@ static int tps_setup(struct i2c_client *client, void *context)
|
|||||||
{
|
{
|
||||||
if (!IS_BUILTIN(CONFIG_TPS65010))
|
if (!IS_BUILTIN(CONFIG_TPS65010))
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V |
|
tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V |
|
||||||
TPS_LDO1_ENABLE | TPS_VLDO1_3_0V);
|
TPS_LDO1_ENABLE | TPS_VLDO1_3_0V);
|
||||||
|
|
||||||
@ -394,6 +394,8 @@ static void __init h2_init(void)
|
|||||||
BUG_ON(gpio_request(H2_NAND_RB_GPIO_PIN, "NAND ready") < 0);
|
BUG_ON(gpio_request(H2_NAND_RB_GPIO_PIN, "NAND ready") < 0);
|
||||||
gpio_direction_input(H2_NAND_RB_GPIO_PIN);
|
gpio_direction_input(H2_NAND_RB_GPIO_PIN);
|
||||||
|
|
||||||
|
gpiod_add_lookup_table(&isp1301_gpiod_table);
|
||||||
|
|
||||||
omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
|
omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
|
||||||
omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
|
omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
|
||||||
|
|
||||||
|
@ -168,6 +168,7 @@ config ARCH_MEDIATEK
|
|||||||
|
|
||||||
config ARCH_MESON
|
config ARCH_MESON
|
||||||
bool "Amlogic Platforms"
|
bool "Amlogic Platforms"
|
||||||
|
select COMMON_CLK
|
||||||
select MESON_IRQ_GPIO
|
select MESON_IRQ_GPIO
|
||||||
help
|
help
|
||||||
This enables support for the arm64 based Amlogic SoCs
|
This enables support for the arm64 based Amlogic SoCs
|
||||||
|
@ -46,7 +46,8 @@ phy0: ethernet-phy@4 {
|
|||||||
eee-broken-100tx;
|
eee-broken-100tx;
|
||||||
qca,clk-out-frequency = <125000000>;
|
qca,clk-out-frequency = <125000000>;
|
||||||
qca,clk-out-strength = <AR803X_STRENGTH_FULL>;
|
qca,clk-out-strength = <AR803X_STRENGTH_FULL>;
|
||||||
vddio-supply = <&vddh>;
|
qca,keep-pll-enabled;
|
||||||
|
vddio-supply = <&vddio>;
|
||||||
|
|
||||||
vddio: vddio-regulator {
|
vddio: vddio-regulator {
|
||||||
regulator-name = "VDDIO";
|
regulator-name = "VDDIO";
|
||||||
|
@ -31,11 +31,10 @@ phy1: ethernet-phy@4 {
|
|||||||
reg = <0x4>;
|
reg = <0x4>;
|
||||||
eee-broken-1000t;
|
eee-broken-1000t;
|
||||||
eee-broken-100tx;
|
eee-broken-100tx;
|
||||||
|
|
||||||
qca,clk-out-frequency = <125000000>;
|
qca,clk-out-frequency = <125000000>;
|
||||||
qca,clk-out-strength = <AR803X_STRENGTH_FULL>;
|
qca,clk-out-strength = <AR803X_STRENGTH_FULL>;
|
||||||
|
qca,keep-pll-enabled;
|
||||||
vddio-supply = <&vddh>;
|
vddio-supply = <&vddio>;
|
||||||
|
|
||||||
vddio: vddio-regulator {
|
vddio: vddio-regulator {
|
||||||
regulator-name = "VDDIO";
|
regulator-name = "VDDIO";
|
||||||
|
@ -201,8 +201,8 @@ soc: soc {
|
|||||||
ddr: memory-controller@1080000 {
|
ddr: memory-controller@1080000 {
|
||||||
compatible = "fsl,qoriq-memory-controller";
|
compatible = "fsl,qoriq-memory-controller";
|
||||||
reg = <0x0 0x1080000 0x0 0x1000>;
|
reg = <0x0 0x1080000 0x0 0x1000>;
|
||||||
interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
big-endian;
|
little-endian;
|
||||||
};
|
};
|
||||||
|
|
||||||
dcfg: syscon@1e00000 {
|
dcfg: syscon@1e00000 {
|
||||||
|
@ -88,11 +88,11 @@ codec2: codec@18 {
|
|||||||
pinctrl-0 = <&pinctrl_codec2>;
|
pinctrl-0 = <&pinctrl_codec2>;
|
||||||
reg = <0x18>;
|
reg = <0x18>;
|
||||||
#sound-dai-cells = <0>;
|
#sound-dai-cells = <0>;
|
||||||
HPVDD-supply = <®_3p3v>;
|
HPVDD-supply = <®_gen_3p3>;
|
||||||
SPRVDD-supply = <®_3p3v>;
|
SPRVDD-supply = <®_gen_3p3>;
|
||||||
SPLVDD-supply = <®_3p3v>;
|
SPLVDD-supply = <®_gen_3p3>;
|
||||||
AVDD-supply = <®_3p3v>;
|
AVDD-supply = <®_gen_3p3>;
|
||||||
IOVDD-supply = <®_3p3v>;
|
IOVDD-supply = <®_gen_3p3>;
|
||||||
DVDD-supply = <&vgen4_reg>;
|
DVDD-supply = <&vgen4_reg>;
|
||||||
reset-gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
|
reset-gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
|
||||||
};
|
};
|
||||||
|
@ -45,8 +45,8 @@ pcie1_refclk: clock-pcie1-refclk {
|
|||||||
reg_12p0_main: regulator-12p0-main {
|
reg_12p0_main: regulator-12p0-main {
|
||||||
compatible = "regulator-fixed";
|
compatible = "regulator-fixed";
|
||||||
regulator-name = "12V_MAIN";
|
regulator-name = "12V_MAIN";
|
||||||
regulator-min-microvolt = <5000000>;
|
regulator-min-microvolt = <12000000>;
|
||||||
regulator-max-microvolt = <5000000>;
|
regulator-max-microvolt = <12000000>;
|
||||||
regulator-always-on;
|
regulator-always-on;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,15 +77,6 @@ reg_gen_3p3: regulator-gen-3p3 {
|
|||||||
regulator-always-on;
|
regulator-always-on;
|
||||||
};
|
};
|
||||||
|
|
||||||
reg_3p3v: regulator-3p3v {
|
|
||||||
compatible = "regulator-fixed";
|
|
||||||
vin-supply = <®_3p3_main>;
|
|
||||||
regulator-name = "GEN_3V3";
|
|
||||||
regulator-min-microvolt = <3300000>;
|
|
||||||
regulator-max-microvolt = <3300000>;
|
|
||||||
regulator-always-on;
|
|
||||||
};
|
|
||||||
|
|
||||||
reg_usdhc2_vmmc: regulator-vsd-3v3 {
|
reg_usdhc2_vmmc: regulator-vsd-3v3 {
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&pinctrl_reg_usdhc2>;
|
pinctrl-0 = <&pinctrl_reg_usdhc2>;
|
||||||
@ -415,11 +406,11 @@ codec1: codec@18 {
|
|||||||
pinctrl-0 = <&pinctrl_codec1>;
|
pinctrl-0 = <&pinctrl_codec1>;
|
||||||
reg = <0x18>;
|
reg = <0x18>;
|
||||||
#sound-dai-cells = <0>;
|
#sound-dai-cells = <0>;
|
||||||
HPVDD-supply = <®_3p3v>;
|
HPVDD-supply = <®_gen_3p3>;
|
||||||
SPRVDD-supply = <®_3p3v>;
|
SPRVDD-supply = <®_gen_3p3>;
|
||||||
SPLVDD-supply = <®_3p3v>;
|
SPLVDD-supply = <®_gen_3p3>;
|
||||||
AVDD-supply = <®_3p3v>;
|
AVDD-supply = <®_gen_3p3>;
|
||||||
IOVDD-supply = <®_3p3v>;
|
IOVDD-supply = <®_gen_3p3>;
|
||||||
DVDD-supply = <&vgen4_reg>;
|
DVDD-supply = <&vgen4_reg>;
|
||||||
reset-gpios = <&gpio3 3 GPIO_ACTIVE_LOW>;
|
reset-gpios = <&gpio3 3 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
|
@ -85,6 +85,8 @@ main_navss: bus@30000000 {
|
|||||||
#size-cells = <2>;
|
#size-cells = <2>;
|
||||||
ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>;
|
ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>;
|
||||||
ti,sci-dev-id = <199>;
|
ti,sci-dev-id = <199>;
|
||||||
|
dma-coherent;
|
||||||
|
dma-ranges;
|
||||||
|
|
||||||
main_navss_intr: interrupt-controller1 {
|
main_navss_intr: interrupt-controller1 {
|
||||||
compatible = "ti,sci-intr";
|
compatible = "ti,sci-intr";
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#define __KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2 12
|
#define __KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2 12
|
||||||
#define __KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs 13
|
#define __KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs 13
|
||||||
#define __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_aprs 14
|
#define __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_aprs 14
|
||||||
|
#define __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc 15
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
@ -715,11 +715,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run->immediate_exit)
|
|
||||||
return -EINTR;
|
|
||||||
|
|
||||||
vcpu_load(vcpu);
|
vcpu_load(vcpu);
|
||||||
|
|
||||||
|
if (run->immediate_exit) {
|
||||||
|
ret = -EINTR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
kvm_sigset_activate(vcpu);
|
kvm_sigset_activate(vcpu);
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -892,6 +894,18 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
kvm_sigset_deactivate(vcpu);
|
kvm_sigset_deactivate(vcpu);
|
||||||
|
|
||||||
|
out:
|
||||||
|
/*
|
||||||
|
* In the unlikely event that we are returning to userspace
|
||||||
|
* with pending exceptions or PC adjustment, commit these
|
||||||
|
* adjustments in order to give userspace a consistent view of
|
||||||
|
* the vcpu state. Note that this relies on __kvm_adjust_pc()
|
||||||
|
* being preempt-safe on VHE.
|
||||||
|
*/
|
||||||
|
if (unlikely(vcpu->arch.flags & (KVM_ARM64_PENDING_EXCEPTION |
|
||||||
|
KVM_ARM64_INCREMENT_PC)))
|
||||||
|
kvm_call_hyp(__kvm_adjust_pc, vcpu);
|
||||||
|
|
||||||
vcpu_put(vcpu);
|
vcpu_put(vcpu);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -331,8 +331,8 @@ static void kvm_inject_exception(struct kvm_vcpu *vcpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust the guest PC on entry, depending on flags provided by EL1
|
* Adjust the guest PC (and potentially exception state) depending on
|
||||||
* for the purpose of emulation (MMIO, sysreg) or exception injection.
|
* flags provided by the emulation code.
|
||||||
*/
|
*/
|
||||||
void __kvm_adjust_pc(struct kvm_vcpu *vcpu)
|
void __kvm_adjust_pc(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,13 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
|
|||||||
cpu_reg(host_ctxt, 1) = __kvm_vcpu_run(kern_hyp_va(vcpu));
|
cpu_reg(host_ctxt, 1) = __kvm_vcpu_run(kern_hyp_va(vcpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle___kvm_adjust_pc(struct kvm_cpu_context *host_ctxt)
|
||||||
|
{
|
||||||
|
DECLARE_REG(struct kvm_vcpu *, vcpu, host_ctxt, 1);
|
||||||
|
|
||||||
|
__kvm_adjust_pc(kern_hyp_va(vcpu));
|
||||||
|
}
|
||||||
|
|
||||||
static void handle___kvm_flush_vm_context(struct kvm_cpu_context *host_ctxt)
|
static void handle___kvm_flush_vm_context(struct kvm_cpu_context *host_ctxt)
|
||||||
{
|
{
|
||||||
__kvm_flush_vm_context();
|
__kvm_flush_vm_context();
|
||||||
@ -112,6 +119,7 @@ typedef void (*hcall_t)(struct kvm_cpu_context *);
|
|||||||
|
|
||||||
static const hcall_t host_hcall[] = {
|
static const hcall_t host_hcall[] = {
|
||||||
HANDLE_FUNC(__kvm_vcpu_run),
|
HANDLE_FUNC(__kvm_vcpu_run),
|
||||||
|
HANDLE_FUNC(__kvm_adjust_pc),
|
||||||
HANDLE_FUNC(__kvm_flush_vm_context),
|
HANDLE_FUNC(__kvm_flush_vm_context),
|
||||||
HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa),
|
HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa),
|
||||||
HANDLE_FUNC(__kvm_tlb_flush_vmid),
|
HANDLE_FUNC(__kvm_tlb_flush_vmid),
|
||||||
|
@ -157,31 +157,29 @@ unsigned long _page_cachable_default;
|
|||||||
EXPORT_SYMBOL(_page_cachable_default);
|
EXPORT_SYMBOL(_page_cachable_default);
|
||||||
|
|
||||||
#define PM(p) __pgprot(_page_cachable_default | (p))
|
#define PM(p) __pgprot(_page_cachable_default | (p))
|
||||||
#define PVA(p) PM(_PAGE_VALID | _PAGE_ACCESSED | (p))
|
|
||||||
|
|
||||||
static inline void setup_protection_map(void)
|
static inline void setup_protection_map(void)
|
||||||
{
|
{
|
||||||
protection_map[0] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
|
protection_map[0] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
|
||||||
protection_map[1] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC);
|
protection_map[1] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC);
|
||||||
protection_map[2] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
|
protection_map[2] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
|
||||||
protection_map[3] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC);
|
protection_map[3] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC);
|
||||||
protection_map[4] = PVA(_PAGE_PRESENT);
|
protection_map[4] = PM(_PAGE_PRESENT);
|
||||||
protection_map[5] = PVA(_PAGE_PRESENT);
|
protection_map[5] = PM(_PAGE_PRESENT);
|
||||||
protection_map[6] = PVA(_PAGE_PRESENT);
|
protection_map[6] = PM(_PAGE_PRESENT);
|
||||||
protection_map[7] = PVA(_PAGE_PRESENT);
|
protection_map[7] = PM(_PAGE_PRESENT);
|
||||||
|
|
||||||
protection_map[8] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
|
protection_map[8] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
|
||||||
protection_map[9] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC);
|
protection_map[9] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC);
|
||||||
protection_map[10] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE |
|
protection_map[10] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE |
|
||||||
_PAGE_NO_READ);
|
_PAGE_NO_READ);
|
||||||
protection_map[11] = PVA(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE);
|
protection_map[11] = PM(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE);
|
||||||
protection_map[12] = PVA(_PAGE_PRESENT);
|
protection_map[12] = PM(_PAGE_PRESENT);
|
||||||
protection_map[13] = PVA(_PAGE_PRESENT);
|
protection_map[13] = PM(_PAGE_PRESENT);
|
||||||
protection_map[14] = PVA(_PAGE_PRESENT);
|
protection_map[14] = PM(_PAGE_PRESENT | _PAGE_WRITE);
|
||||||
protection_map[15] = PVA(_PAGE_PRESENT);
|
protection_map[15] = PM(_PAGE_PRESENT | _PAGE_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef _PVA
|
|
||||||
#undef PM
|
#undef PM
|
||||||
|
|
||||||
void cpu_cache_init(void)
|
void cpu_cache_init(void)
|
||||||
|
@ -108,7 +108,6 @@ int arch_prepare_kprobe(struct kprobe *p)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct kprobe *prev;
|
struct kprobe *prev;
|
||||||
struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
|
struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr);
|
||||||
struct ppc_inst prefix = ppc_inst_read((struct ppc_inst *)(p->addr - 1));
|
|
||||||
|
|
||||||
if ((unsigned long)p->addr & 0x03) {
|
if ((unsigned long)p->addr & 0x03) {
|
||||||
printk("Attempt to register kprobe at an unaligned address\n");
|
printk("Attempt to register kprobe at an unaligned address\n");
|
||||||
@ -116,7 +115,8 @@ int arch_prepare_kprobe(struct kprobe *p)
|
|||||||
} else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
|
} else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
|
||||||
printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
|
printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
} else if (ppc_inst_prefixed(prefix)) {
|
} else if ((unsigned long)p->addr & ~PAGE_MASK &&
|
||||||
|
ppc_inst_prefixed(ppc_inst_read((struct ppc_inst *)(p->addr - 1)))) {
|
||||||
printk("Cannot register a kprobe on the second word of prefixed instruction\n");
|
printk("Cannot register a kprobe on the second word of prefixed instruction\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -4418,7 +4418,6 @@ static int kvmppc_vcpu_run_hv(struct kvm_vcpu *vcpu)
|
|||||||
mtspr(SPRN_EBBRR, ebb_regs[1]);
|
mtspr(SPRN_EBBRR, ebb_regs[1]);
|
||||||
mtspr(SPRN_BESCR, ebb_regs[2]);
|
mtspr(SPRN_BESCR, ebb_regs[2]);
|
||||||
mtspr(SPRN_TAR, user_tar);
|
mtspr(SPRN_TAR, user_tar);
|
||||||
mtspr(SPRN_FSCR, current->thread.fscr);
|
|
||||||
}
|
}
|
||||||
mtspr(SPRN_VRSAVE, user_vrsave);
|
mtspr(SPRN_VRSAVE, user_vrsave);
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
|
|||||||
#define STACK_SLOT_UAMOR (SFS-88)
|
#define STACK_SLOT_UAMOR (SFS-88)
|
||||||
#define STACK_SLOT_DAWR1 (SFS-96)
|
#define STACK_SLOT_DAWR1 (SFS-96)
|
||||||
#define STACK_SLOT_DAWRX1 (SFS-104)
|
#define STACK_SLOT_DAWRX1 (SFS-104)
|
||||||
|
#define STACK_SLOT_FSCR (SFS-112)
|
||||||
/* the following is used by the P9 short path */
|
/* the following is used by the P9 short path */
|
||||||
#define STACK_SLOT_NVGPRS (SFS-152) /* 18 gprs */
|
#define STACK_SLOT_NVGPRS (SFS-152) /* 18 gprs */
|
||||||
|
|
||||||
@ -686,6 +687,8 @@ BEGIN_FTR_SECTION
|
|||||||
std r6, STACK_SLOT_DAWR0(r1)
|
std r6, STACK_SLOT_DAWR0(r1)
|
||||||
std r7, STACK_SLOT_DAWRX0(r1)
|
std r7, STACK_SLOT_DAWRX0(r1)
|
||||||
std r8, STACK_SLOT_IAMR(r1)
|
std r8, STACK_SLOT_IAMR(r1)
|
||||||
|
mfspr r5, SPRN_FSCR
|
||||||
|
std r5, STACK_SLOT_FSCR(r1)
|
||||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||||
BEGIN_FTR_SECTION
|
BEGIN_FTR_SECTION
|
||||||
mfspr r6, SPRN_DAWR1
|
mfspr r6, SPRN_DAWR1
|
||||||
@ -1663,6 +1666,10 @@ FTR_SECTION_ELSE
|
|||||||
ld r7, STACK_SLOT_HFSCR(r1)
|
ld r7, STACK_SLOT_HFSCR(r1)
|
||||||
mtspr SPRN_HFSCR, r7
|
mtspr SPRN_HFSCR, r7
|
||||||
ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
|
ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
|
||||||
|
BEGIN_FTR_SECTION
|
||||||
|
ld r5, STACK_SLOT_FSCR(r1)
|
||||||
|
mtspr SPRN_FSCR, r5
|
||||||
|
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||||
/*
|
/*
|
||||||
* Restore various registers to 0, where non-zero values
|
* Restore various registers to 0, where non-zero values
|
||||||
* set by the guest could disrupt the host.
|
* set by the guest could disrupt the host.
|
||||||
|
@ -23,7 +23,7 @@ ifneq ($(c-gettimeofday-y),)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# Build rules
|
# Build rules
|
||||||
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-dummy.o
|
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-syms.S
|
||||||
obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
|
obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
|
||||||
|
|
||||||
obj-y += vdso.o vdso-syms.o
|
obj-y += vdso.o vdso-syms.o
|
||||||
@ -41,7 +41,7 @@ KASAN_SANITIZE := n
|
|||||||
$(obj)/vdso.o: $(obj)/vdso.so
|
$(obj)/vdso.o: $(obj)/vdso.so
|
||||||
|
|
||||||
# link rule for the .so file, .lds has to be first
|
# link rule for the .so file, .lds has to be first
|
||||||
$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE
|
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
|
||||||
$(call if_changed,vdsold)
|
$(call if_changed,vdsold)
|
||||||
LDFLAGS_vdso.so.dbg = -shared -s -soname=linux-vdso.so.1 \
|
LDFLAGS_vdso.so.dbg = -shared -s -soname=linux-vdso.so.1 \
|
||||||
--build-id=sha1 --hash-style=both --eh-frame-hdr
|
--build-id=sha1 --hash-style=both --eh-frame-hdr
|
||||||
|
@ -174,6 +174,7 @@ static inline int apic_is_clustered_box(void)
|
|||||||
extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
|
extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
|
||||||
extern void lapic_assign_system_vectors(void);
|
extern void lapic_assign_system_vectors(void);
|
||||||
extern void lapic_assign_legacy_vector(unsigned int isairq, bool replace);
|
extern void lapic_assign_legacy_vector(unsigned int isairq, bool replace);
|
||||||
|
extern void lapic_update_legacy_vectors(void);
|
||||||
extern void lapic_online(void);
|
extern void lapic_online(void);
|
||||||
extern void lapic_offline(void);
|
extern void lapic_offline(void);
|
||||||
extern bool apic_needs_pit(void);
|
extern bool apic_needs_pit(void);
|
||||||
|
@ -56,11 +56,8 @@
|
|||||||
# define DISABLE_PTI (1 << (X86_FEATURE_PTI & 31))
|
# define DISABLE_PTI (1 << (X86_FEATURE_PTI & 31))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_IOMMU_SUPPORT
|
/* Force disable because it's broken beyond repair */
|
||||||
# define DISABLE_ENQCMD 0
|
#define DISABLE_ENQCMD (1 << (X86_FEATURE_ENQCMD & 31))
|
||||||
#else
|
|
||||||
# define DISABLE_ENQCMD (1 << (X86_FEATURE_ENQCMD & 31))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_SGX
|
#ifdef CONFIG_X86_SGX
|
||||||
# define DISABLE_SGX 0
|
# define DISABLE_SGX 0
|
||||||
|
@ -106,10 +106,6 @@ extern int cpu_has_xfeatures(u64 xfeatures_mask, const char **feature_name);
|
|||||||
*/
|
*/
|
||||||
#define PASID_DISABLED 0
|
#define PASID_DISABLED 0
|
||||||
|
|
||||||
#ifdef CONFIG_IOMMU_SUPPORT
|
|
||||||
/* Update current's PASID MSR/state by mm's PASID. */
|
|
||||||
void update_pasid(void);
|
|
||||||
#else
|
|
||||||
static inline void update_pasid(void) { }
|
static inline void update_pasid(void) { }
|
||||||
#endif
|
|
||||||
#endif /* _ASM_X86_FPU_API_H */
|
#endif /* _ASM_X86_FPU_API_H */
|
||||||
|
@ -584,13 +584,6 @@ static inline void switch_fpu_finish(struct fpu *new_fpu)
|
|||||||
pkru_val = pk->pkru;
|
pkru_val = pk->pkru;
|
||||||
}
|
}
|
||||||
__write_pkru(pkru_val);
|
__write_pkru(pkru_val);
|
||||||
|
|
||||||
/*
|
|
||||||
* Expensive PASID MSR write will be avoided in update_pasid() because
|
|
||||||
* TIF_NEED_FPU_LOAD was set. And the PASID state won't be updated
|
|
||||||
* unless it's different from mm->pasid to reduce overhead.
|
|
||||||
*/
|
|
||||||
update_pasid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _ASM_X86_FPU_INTERNAL_H */
|
#endif /* _ASM_X86_FPU_INTERNAL_H */
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <uapi/asm/kvm_para.h>
|
#include <uapi/asm/kvm_para.h>
|
||||||
|
|
||||||
extern void kvmclock_init(void);
|
|
||||||
|
|
||||||
#ifdef CONFIG_KVM_GUEST
|
#ifdef CONFIG_KVM_GUEST
|
||||||
bool kvm_check_and_clear_guest_paused(void);
|
bool kvm_check_and_clear_guest_paused(void);
|
||||||
#else
|
#else
|
||||||
@ -86,13 +84,14 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KVM_GUEST
|
#ifdef CONFIG_KVM_GUEST
|
||||||
|
void kvmclock_init(void);
|
||||||
|
void kvmclock_disable(void);
|
||||||
bool kvm_para_available(void);
|
bool kvm_para_available(void);
|
||||||
unsigned int kvm_arch_para_features(void);
|
unsigned int kvm_arch_para_features(void);
|
||||||
unsigned int kvm_arch_para_hints(void);
|
unsigned int kvm_arch_para_hints(void);
|
||||||
void kvm_async_pf_task_wait_schedule(u32 token);
|
void kvm_async_pf_task_wait_schedule(u32 token);
|
||||||
void kvm_async_pf_task_wake(u32 token);
|
void kvm_async_pf_task_wake(u32 token);
|
||||||
u32 kvm_read_and_reset_apf_flags(void);
|
u32 kvm_read_and_reset_apf_flags(void);
|
||||||
void kvm_disable_steal_time(void);
|
|
||||||
bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token);
|
bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token);
|
||||||
|
|
||||||
DECLARE_STATIC_KEY_FALSE(kvm_async_pf_enabled);
|
DECLARE_STATIC_KEY_FALSE(kvm_async_pf_enabled);
|
||||||
@ -137,11 +136,6 @@ static inline u32 kvm_read_and_reset_apf_flags(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void kvm_disable_steal_time(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __always_inline bool kvm_handle_async_pf(struct pt_regs *regs, u32 token)
|
static __always_inline bool kvm_handle_async_pf(struct pt_regs *regs, u32 token)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
#define _ASM_X86_THERMAL_H
|
#define _ASM_X86_THERMAL_H
|
||||||
|
|
||||||
#ifdef CONFIG_X86_THERMAL_VECTOR
|
#ifdef CONFIG_X86_THERMAL_VECTOR
|
||||||
|
void therm_lvt_init(void);
|
||||||
void intel_init_thermal(struct cpuinfo_x86 *c);
|
void intel_init_thermal(struct cpuinfo_x86 *c);
|
||||||
bool x86_thermal_enabled(void);
|
bool x86_thermal_enabled(void);
|
||||||
void intel_thermal_interrupt(void);
|
void intel_thermal_interrupt(void);
|
||||||
#else
|
#else
|
||||||
static inline void intel_init_thermal(struct cpuinfo_x86 *c) { }
|
static inline void therm_lvt_init(void) { }
|
||||||
|
static inline void intel_init_thermal(struct cpuinfo_x86 *c) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _ASM_X86_THERMAL_H */
|
#endif /* _ASM_X86_THERMAL_H */
|
||||||
|
@ -2604,6 +2604,7 @@ static void __init apic_bsp_setup(bool upmode)
|
|||||||
end_local_APIC_setup();
|
end_local_APIC_setup();
|
||||||
irq_remap_enable_fault_handling();
|
irq_remap_enable_fault_handling();
|
||||||
setup_IO_APIC();
|
setup_IO_APIC();
|
||||||
|
lapic_update_legacy_vectors();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_UP_LATE_INIT
|
#ifdef CONFIG_UP_LATE_INIT
|
||||||
|
@ -730,6 +730,26 @@ void lapic_assign_legacy_vector(unsigned int irq, bool replace)
|
|||||||
irq_matrix_assign_system(vector_matrix, ISA_IRQ_VECTOR(irq), replace);
|
irq_matrix_assign_system(vector_matrix, ISA_IRQ_VECTOR(irq), replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init lapic_update_legacy_vectors(void)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_X86_IO_APIC) && nr_ioapics > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the IO/APIC is disabled via config, kernel command line or
|
||||||
|
* lack of enumeration then all legacy interrupts are routed
|
||||||
|
* through the PIC. Make sure that they are marked as legacy
|
||||||
|
* vectors. PIC_CASCADE_IRQ has already been marked in
|
||||||
|
* lapic_assign_system_vectors().
|
||||||
|
*/
|
||||||
|
for (i = 0; i < nr_legacy_irqs(); i++) {
|
||||||
|
if (i != PIC_CASCADE_IR)
|
||||||
|
lapic_assign_legacy_vector(i, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void __init lapic_assign_system_vectors(void)
|
void __init lapic_assign_system_vectors(void)
|
||||||
{
|
{
|
||||||
unsigned int i, vector = 0;
|
unsigned int i, vector = 0;
|
||||||
|
@ -1402,60 +1402,3 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PROC_PID_ARCH_STATUS */
|
#endif /* CONFIG_PROC_PID_ARCH_STATUS */
|
||||||
|
|
||||||
#ifdef CONFIG_IOMMU_SUPPORT
|
|
||||||
void update_pasid(void)
|
|
||||||
{
|
|
||||||
u64 pasid_state;
|
|
||||||
u32 pasid;
|
|
||||||
|
|
||||||
if (!cpu_feature_enabled(X86_FEATURE_ENQCMD))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!current->mm)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pasid = READ_ONCE(current->mm->pasid);
|
|
||||||
/* Set the valid bit in the PASID MSR/state only for valid pasid. */
|
|
||||||
pasid_state = pasid == PASID_DISABLED ?
|
|
||||||
pasid : pasid | MSR_IA32_PASID_VALID;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No need to hold fregs_lock() since the task's fpstate won't
|
|
||||||
* be changed by others (e.g. ptrace) while the task is being
|
|
||||||
* switched to or is in IPI.
|
|
||||||
*/
|
|
||||||
if (!test_thread_flag(TIF_NEED_FPU_LOAD)) {
|
|
||||||
/* The MSR is active and can be directly updated. */
|
|
||||||
wrmsrl(MSR_IA32_PASID, pasid_state);
|
|
||||||
} else {
|
|
||||||
struct fpu *fpu = ¤t->thread.fpu;
|
|
||||||
struct ia32_pasid_state *ppasid_state;
|
|
||||||
struct xregs_state *xsave;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The CPU's xstate registers are not currently active. Just
|
|
||||||
* update the PASID state in the memory buffer here. The
|
|
||||||
* PASID MSR will be loaded when returning to user mode.
|
|
||||||
*/
|
|
||||||
xsave = &fpu->state.xsave;
|
|
||||||
xsave->header.xfeatures |= XFEATURE_MASK_PASID;
|
|
||||||
ppasid_state = get_xsave_addr(xsave, XFEATURE_PASID);
|
|
||||||
/*
|
|
||||||
* Since XFEATURE_MASK_PASID is set in xfeatures, ppasid_state
|
|
||||||
* won't be NULL and no need to check its value.
|
|
||||||
*
|
|
||||||
* Only update the task's PASID state when it's different
|
|
||||||
* from the mm's pasid.
|
|
||||||
*/
|
|
||||||
if (ppasid_state->pasid != pasid_state) {
|
|
||||||
/*
|
|
||||||
* Invalid fpregs so that state restoring will pick up
|
|
||||||
* the PASID state.
|
|
||||||
*/
|
|
||||||
__fpu_invalidate_fpregs_state(fpu);
|
|
||||||
ppasid_state->pasid = pasid_state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_IOMMU_SUPPORT */
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <linux/kprobes.h>
|
#include <linux/kprobes.h>
|
||||||
#include <linux/nmi.h>
|
#include <linux/nmi.h>
|
||||||
#include <linux/swait.h>
|
#include <linux/swait.h>
|
||||||
|
#include <linux/syscore_ops.h>
|
||||||
#include <asm/timer.h>
|
#include <asm/timer.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include <asm/tlb.h>
|
#include <asm/tlb.h>
|
||||||
#include <asm/cpuidle_haltpoll.h>
|
#include <asm/cpuidle_haltpoll.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
#include <asm/reboot.h>
|
||||||
#include <asm/svm.h>
|
#include <asm/svm.h>
|
||||||
|
|
||||||
DEFINE_STATIC_KEY_FALSE(kvm_async_pf_enabled);
|
DEFINE_STATIC_KEY_FALSE(kvm_async_pf_enabled);
|
||||||
@ -374,6 +376,14 @@ static void kvm_pv_disable_apf(void)
|
|||||||
pr_info("Unregister pv shared memory for cpu %d\n", smp_processor_id());
|
pr_info("Unregister pv shared memory for cpu %d\n", smp_processor_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kvm_disable_steal_time(void)
|
||||||
|
{
|
||||||
|
if (!has_steal_clock)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wrmsr(MSR_KVM_STEAL_TIME, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void kvm_pv_guest_cpu_reboot(void *unused)
|
static void kvm_pv_guest_cpu_reboot(void *unused)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -416,14 +426,6 @@ static u64 kvm_steal_clock(int cpu)
|
|||||||
return steal;
|
return steal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_disable_steal_time(void)
|
|
||||||
{
|
|
||||||
if (!has_steal_clock)
|
|
||||||
return;
|
|
||||||
|
|
||||||
wrmsr(MSR_KVM_STEAL_TIME, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void __set_percpu_decrypted(void *ptr, unsigned long size)
|
static inline void __set_percpu_decrypted(void *ptr, unsigned long size)
|
||||||
{
|
{
|
||||||
early_set_memory_decrypted((unsigned long) ptr, size);
|
early_set_memory_decrypted((unsigned long) ptr, size);
|
||||||
@ -460,6 +462,27 @@ static bool pv_tlb_flush_supported(void)
|
|||||||
|
|
||||||
static DEFINE_PER_CPU(cpumask_var_t, __pv_cpu_mask);
|
static DEFINE_PER_CPU(cpumask_var_t, __pv_cpu_mask);
|
||||||
|
|
||||||
|
static void kvm_guest_cpu_offline(bool shutdown)
|
||||||
|
{
|
||||||
|
kvm_disable_steal_time();
|
||||||
|
if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
|
||||||
|
wrmsrl(MSR_KVM_PV_EOI_EN, 0);
|
||||||
|
kvm_pv_disable_apf();
|
||||||
|
if (!shutdown)
|
||||||
|
apf_task_wake_all();
|
||||||
|
kvmclock_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kvm_cpu_online(unsigned int cpu)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
kvm_guest_cpu_init();
|
||||||
|
local_irq_restore(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
||||||
static bool pv_ipi_supported(void)
|
static bool pv_ipi_supported(void)
|
||||||
@ -587,30 +610,47 @@ static void __init kvm_smp_prepare_boot_cpu(void)
|
|||||||
kvm_spinlock_init();
|
kvm_spinlock_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kvm_guest_cpu_offline(void)
|
|
||||||
{
|
|
||||||
kvm_disable_steal_time();
|
|
||||||
if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
|
|
||||||
wrmsrl(MSR_KVM_PV_EOI_EN, 0);
|
|
||||||
kvm_pv_disable_apf();
|
|
||||||
apf_task_wake_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int kvm_cpu_online(unsigned int cpu)
|
|
||||||
{
|
|
||||||
local_irq_disable();
|
|
||||||
kvm_guest_cpu_init();
|
|
||||||
local_irq_enable();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int kvm_cpu_down_prepare(unsigned int cpu)
|
static int kvm_cpu_down_prepare(unsigned int cpu)
|
||||||
{
|
{
|
||||||
local_irq_disable();
|
unsigned long flags;
|
||||||
kvm_guest_cpu_offline();
|
|
||||||
local_irq_enable();
|
local_irq_save(flags);
|
||||||
|
kvm_guest_cpu_offline(false);
|
||||||
|
local_irq_restore(flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int kvm_suspend(void)
|
||||||
|
{
|
||||||
|
kvm_guest_cpu_offline(false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kvm_resume(void)
|
||||||
|
{
|
||||||
|
kvm_cpu_online(raw_smp_processor_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct syscore_ops kvm_syscore_ops = {
|
||||||
|
.suspend = kvm_suspend,
|
||||||
|
.resume = kvm_resume,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After a PV feature is registered, the host will keep writing to the
|
||||||
|
* registered memory location. If the guest happens to shutdown, this memory
|
||||||
|
* won't be valid. In cases like kexec, in which you install a new kernel, this
|
||||||
|
* means a random memory location will be kept being written.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_KEXEC_CORE
|
||||||
|
static void kvm_crash_shutdown(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
kvm_guest_cpu_offline(true);
|
||||||
|
native_machine_crash_shutdown(regs);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void kvm_flush_tlb_others(const struct cpumask *cpumask,
|
static void kvm_flush_tlb_others(const struct cpumask *cpumask,
|
||||||
@ -681,6 +721,12 @@ static void __init kvm_guest_init(void)
|
|||||||
kvm_guest_cpu_init();
|
kvm_guest_cpu_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KEXEC_CORE
|
||||||
|
machine_ops.crash_shutdown = kvm_crash_shutdown;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
register_syscore_ops(&kvm_syscore_ops);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hard lockup detection is enabled by default. Disable it, as guests
|
* Hard lockup detection is enabled by default. Disable it, as guests
|
||||||
* can get false positives too easily, for example if the host is
|
* can get false positives too easily, for example if the host is
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <asm/hypervisor.h>
|
#include <asm/hypervisor.h>
|
||||||
#include <asm/mem_encrypt.h>
|
#include <asm/mem_encrypt.h>
|
||||||
#include <asm/x86_init.h>
|
#include <asm/x86_init.h>
|
||||||
#include <asm/reboot.h>
|
|
||||||
#include <asm/kvmclock.h>
|
#include <asm/kvmclock.h>
|
||||||
|
|
||||||
static int kvmclock __initdata = 1;
|
static int kvmclock __initdata = 1;
|
||||||
@ -203,28 +202,9 @@ static void kvm_setup_secondary_clock(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
void kvmclock_disable(void)
|
||||||
* After the clock is registered, the host will keep writing to the
|
|
||||||
* registered memory location. If the guest happens to shutdown, this memory
|
|
||||||
* won't be valid. In cases like kexec, in which you install a new kernel, this
|
|
||||||
* means a random memory location will be kept being written. So before any
|
|
||||||
* kind of shutdown from our side, we unregister the clock by writing anything
|
|
||||||
* that does not have the 'enable' bit set in the msr
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_KEXEC_CORE
|
|
||||||
static void kvm_crash_shutdown(struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
native_write_msr(msr_kvm_system_time, 0, 0);
|
native_write_msr(msr_kvm_system_time, 0, 0);
|
||||||
kvm_disable_steal_time();
|
|
||||||
native_machine_crash_shutdown(regs);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void kvm_shutdown(void)
|
|
||||||
{
|
|
||||||
native_write_msr(msr_kvm_system_time, 0, 0);
|
|
||||||
kvm_disable_steal_time();
|
|
||||||
native_machine_shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init kvmclock_init_mem(void)
|
static void __init kvmclock_init_mem(void)
|
||||||
@ -351,10 +331,6 @@ void __init kvmclock_init(void)
|
|||||||
#endif
|
#endif
|
||||||
x86_platform.save_sched_clock_state = kvm_save_sched_clock_state;
|
x86_platform.save_sched_clock_state = kvm_save_sched_clock_state;
|
||||||
x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state;
|
x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state;
|
||||||
machine_ops.shutdown = kvm_shutdown;
|
|
||||||
#ifdef CONFIG_KEXEC_CORE
|
|
||||||
machine_ops.crash_shutdown = kvm_crash_shutdown;
|
|
||||||
#endif
|
|
||||||
kvm_get_preset_lpj();
|
kvm_get_preset_lpj();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include <asm/pci-direct.h>
|
#include <asm/pci-direct.h>
|
||||||
#include <asm/prom.h>
|
#include <asm/prom.h>
|
||||||
#include <asm/proto.h>
|
#include <asm/proto.h>
|
||||||
|
#include <asm/thermal.h>
|
||||||
#include <asm/unwind.h>
|
#include <asm/unwind.h>
|
||||||
#include <asm/vsyscall.h>
|
#include <asm/vsyscall.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
@ -1220,6 +1221,14 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
|
|
||||||
x86_init.timers.wallclock_init();
|
x86_init.timers.wallclock_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This needs to run before setup_local_APIC() which soft-disables the
|
||||||
|
* local APIC temporarily and that masks the thermal LVT interrupt,
|
||||||
|
* leading to softlockups on machines which have configured SMI
|
||||||
|
* interrupt delivery.
|
||||||
|
*/
|
||||||
|
therm_lvt_init();
|
||||||
|
|
||||||
mcheck_init();
|
mcheck_init();
|
||||||
|
|
||||||
register_refined_jiffies(CLOCK_TICK_RATE);
|
register_refined_jiffies(CLOCK_TICK_RATE);
|
||||||
|
@ -2532,7 +2532,7 @@ static int cr_interception(struct vcpu_svm *svm)
|
|||||||
err = 0;
|
err = 0;
|
||||||
if (cr >= 16) { /* mov to cr */
|
if (cr >= 16) { /* mov to cr */
|
||||||
cr -= 16;
|
cr -= 16;
|
||||||
val = kvm_register_read(&svm->vcpu, reg);
|
val = kvm_register_readl(&svm->vcpu, reg);
|
||||||
trace_kvm_cr_write(cr, val);
|
trace_kvm_cr_write(cr, val);
|
||||||
switch (cr) {
|
switch (cr) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -2578,7 +2578,7 @@ static int cr_interception(struct vcpu_svm *svm)
|
|||||||
kvm_queue_exception(&svm->vcpu, UD_VECTOR);
|
kvm_queue_exception(&svm->vcpu, UD_VECTOR);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
kvm_register_write(&svm->vcpu, reg, val);
|
kvm_register_writel(&svm->vcpu, reg, val);
|
||||||
trace_kvm_cr_read(cr, val);
|
trace_kvm_cr_read(cr, val);
|
||||||
}
|
}
|
||||||
return kvm_complete_insn_gp(&svm->vcpu, err);
|
return kvm_complete_insn_gp(&svm->vcpu, err);
|
||||||
@ -2643,11 +2643,11 @@ static int dr_interception(struct vcpu_svm *svm)
|
|||||||
dr = svm->vmcb->control.exit_code - SVM_EXIT_READ_DR0;
|
dr = svm->vmcb->control.exit_code - SVM_EXIT_READ_DR0;
|
||||||
if (dr >= 16) { /* mov to DRn */
|
if (dr >= 16) { /* mov to DRn */
|
||||||
dr -= 16;
|
dr -= 16;
|
||||||
val = kvm_register_read(&svm->vcpu, reg);
|
val = kvm_register_readl(&svm->vcpu, reg);
|
||||||
err = kvm_set_dr(&svm->vcpu, dr, val);
|
err = kvm_set_dr(&svm->vcpu, dr, val);
|
||||||
} else {
|
} else {
|
||||||
kvm_get_dr(&svm->vcpu, dr, &val);
|
kvm_get_dr(&svm->vcpu, dr, &val);
|
||||||
kvm_register_write(&svm->vcpu, reg, val);
|
kvm_register_writel(&svm->vcpu, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return kvm_complete_insn_gp(&svm->vcpu, err);
|
return kvm_complete_insn_gp(&svm->vcpu, err);
|
||||||
|
@ -836,8 +836,8 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
|
|||||||
|
|
||||||
if (si_code == SEGV_PKUERR)
|
if (si_code == SEGV_PKUERR)
|
||||||
force_sig_pkuerr((void __user *)address, pkey);
|
force_sig_pkuerr((void __user *)address, pkey);
|
||||||
|
else
|
||||||
force_sig_fault(SIGSEGV, si_code, (void __user *)address);
|
force_sig_fault(SIGSEGV, si_code, (void __user *)address);
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
}
|
}
|
||||||
|
@ -504,10 +504,6 @@ void __init sme_enable(struct boot_params *bp)
|
|||||||
#define AMD_SME_BIT BIT(0)
|
#define AMD_SME_BIT BIT(0)
|
||||||
#define AMD_SEV_BIT BIT(1)
|
#define AMD_SEV_BIT BIT(1)
|
||||||
|
|
||||||
/* Check the SEV MSR whether SEV or SME is enabled */
|
|
||||||
sev_status = __rdmsr(MSR_AMD64_SEV);
|
|
||||||
feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for the SME/SEV feature:
|
* Check for the SME/SEV feature:
|
||||||
* CPUID Fn8000_001F[EAX]
|
* CPUID Fn8000_001F[EAX]
|
||||||
@ -519,11 +515,16 @@ void __init sme_enable(struct boot_params *bp)
|
|||||||
eax = 0x8000001f;
|
eax = 0x8000001f;
|
||||||
ecx = 0;
|
ecx = 0;
|
||||||
native_cpuid(&eax, &ebx, &ecx, &edx);
|
native_cpuid(&eax, &ebx, &ecx, &edx);
|
||||||
if (!(eax & feature_mask))
|
/* Check whether SEV or SME is supported */
|
||||||
|
if (!(eax & (AMD_SEV_BIT | AMD_SME_BIT)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
me_mask = 1UL << (ebx & 0x3f);
|
me_mask = 1UL << (ebx & 0x3f);
|
||||||
|
|
||||||
|
/* Check the SEV MSR whether SEV or SME is enabled */
|
||||||
|
sev_status = __rdmsr(MSR_AMD64_SEV);
|
||||||
|
feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
|
||||||
|
|
||||||
/* Check if memory encryption is enabled */
|
/* Check if memory encryption is enabled */
|
||||||
if (feature_mask == AMD_SME_BIT) {
|
if (feature_mask == AMD_SME_BIT) {
|
||||||
/*
|
/*
|
||||||
|
@ -285,6 +285,14 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
|
||||||
|
|
||||||
|
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
|
||||||
|
"***** Address handler %p\n", object));
|
||||||
|
|
||||||
|
acpi_os_delete_mutex(object->address_space.context_mutex);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1334,6 +1334,34 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sysc_reinit_module(struct sysc *ddata, bool leave_enabled)
|
||||||
|
{
|
||||||
|
struct device *dev = ddata->dev;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
/* Disable target module if it is enabled */
|
||||||
|
if (ddata->enabled) {
|
||||||
|
error = sysc_runtime_suspend(dev);
|
||||||
|
if (error)
|
||||||
|
dev_warn(dev, "reinit suspend failed: %i\n", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable target module */
|
||||||
|
error = sysc_runtime_resume(dev);
|
||||||
|
if (error)
|
||||||
|
dev_warn(dev, "reinit resume failed: %i\n", error);
|
||||||
|
|
||||||
|
if (leave_enabled)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
/* Disable target module if no leave_enabled was set */
|
||||||
|
error = sysc_runtime_suspend(dev);
|
||||||
|
if (error)
|
||||||
|
dev_warn(dev, "reinit suspend failed: %i\n", error);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
static int __maybe_unused sysc_noirq_suspend(struct device *dev)
|
static int __maybe_unused sysc_noirq_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct sysc *ddata;
|
struct sysc *ddata;
|
||||||
@ -1344,12 +1372,18 @@ static int __maybe_unused sysc_noirq_suspend(struct device *dev)
|
|||||||
(SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
|
(SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return pm_runtime_force_suspend(dev);
|
if (!ddata->enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ddata->needs_resume = 1;
|
||||||
|
|
||||||
|
return sysc_runtime_suspend(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __maybe_unused sysc_noirq_resume(struct device *dev)
|
static int __maybe_unused sysc_noirq_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct sysc *ddata;
|
struct sysc *ddata;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
ddata = dev_get_drvdata(dev);
|
ddata = dev_get_drvdata(dev);
|
||||||
|
|
||||||
@ -1357,7 +1391,19 @@ static int __maybe_unused sysc_noirq_resume(struct device *dev)
|
|||||||
(SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
|
(SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return pm_runtime_force_resume(dev);
|
if (ddata->cfg.quirks & SYSC_QUIRK_REINIT_ON_RESUME) {
|
||||||
|
error = sysc_reinit_module(ddata, ddata->needs_resume);
|
||||||
|
if (error)
|
||||||
|
dev_warn(dev, "noirq_resume failed: %i\n", error);
|
||||||
|
} else if (ddata->needs_resume) {
|
||||||
|
error = sysc_runtime_resume(dev);
|
||||||
|
if (error)
|
||||||
|
dev_warn(dev, "noirq_resume failed: %i\n", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
ddata->needs_resume = 0;
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops sysc_pm_ops = {
|
static const struct dev_pm_ops sysc_pm_ops = {
|
||||||
@ -1408,9 +1454,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
|
|||||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||||
/* Uarts on omap4 and later */
|
/* Uarts on omap4 and later */
|
||||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff,
|
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff,
|
||||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
|
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
|
||||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||||
|
|
||||||
/* Quirks that need to be set based on the module address */
|
/* Quirks that need to be set based on the module address */
|
||||||
SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff,
|
SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff,
|
||||||
@ -1466,7 +1512,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
|
|||||||
SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
|
SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
|
||||||
0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
|
0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
|
||||||
SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff,
|
SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff,
|
||||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
|
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY |
|
||||||
|
SYSC_QUIRK_REINIT_ON_RESUME),
|
||||||
SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,
|
SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,
|
||||||
SYSC_MODULE_QUIRK_WDT),
|
SYSC_MODULE_QUIRK_WDT),
|
||||||
/* PRUSS on am3, am4 and am5 */
|
/* PRUSS on am3, am4 and am5 */
|
||||||
|
@ -675,12 +675,12 @@ static int __init idxd_init_module(void)
|
|||||||
* If the CPU does not support MOVDIR64B or ENQCMDS, there's no point in
|
* If the CPU does not support MOVDIR64B or ENQCMDS, there's no point in
|
||||||
* enumerating the device. We can not utilize it.
|
* enumerating the device. We can not utilize it.
|
||||||
*/
|
*/
|
||||||
if (!boot_cpu_has(X86_FEATURE_MOVDIR64B)) {
|
if (!cpu_feature_enabled(X86_FEATURE_MOVDIR64B)) {
|
||||||
pr_warn("idxd driver failed to load without MOVDIR64B.\n");
|
pr_warn("idxd driver failed to load without MOVDIR64B.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!boot_cpu_has(X86_FEATURE_ENQCMD))
|
if (!cpu_feature_enabled(X86_FEATURE_ENQCMD))
|
||||||
pr_warn("Platform does not have ENQCMD(S) support.\n");
|
pr_warn("Platform does not have ENQCMD(S) support.\n");
|
||||||
else
|
else
|
||||||
support_enqcmd = true;
|
support_enqcmd = true;
|
||||||
|
@ -276,8 +276,7 @@ static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
|
|||||||
if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE))
|
if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
n = 0;
|
len = CPER_REC_LEN;
|
||||||
len = CPER_REC_LEN - 1;
|
|
||||||
dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
|
dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
|
||||||
if (bank && device)
|
if (bank && device)
|
||||||
n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
|
n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
|
||||||
@ -286,7 +285,6 @@ static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
|
|||||||
"DIMM location: not present. DMI handle: 0x%.4x ",
|
"DIMM location: not present. DMI handle: 0x%.4x ",
|
||||||
mem->mem_dev_handle);
|
mem->mem_dev_handle);
|
||||||
|
|
||||||
msg[n] = '\0';
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,9 @@ u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm)
|
|||||||
BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name));
|
BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name));
|
||||||
BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(dt_params[0].params));
|
BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(dt_params[0].params));
|
||||||
|
|
||||||
|
if (!fdt)
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
|
for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
|
||||||
node = fdt_path_offset(fdt, dt_params[i].path);
|
node = fdt_path_offset(fdt, dt_params[i].path);
|
||||||
if (node < 0)
|
if (node < 0)
|
||||||
|
@ -103,7 +103,7 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Skip any leading slashes */
|
/* Skip any leading slashes */
|
||||||
while (cmdline[i] == L'/' || cmdline[i] == L'\\')
|
while (i < cmdline_len && (cmdline[i] == L'/' || cmdline[i] == L'\\'))
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
while (--result_len > 0 && i < cmdline_len) {
|
while (--result_len > 0 && i < cmdline_len) {
|
||||||
|
@ -67,11 +67,6 @@ static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(in->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))) {
|
|
||||||
pr_warn("Entry attributes invalid: RO and XP bits both cleared\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PAGE_SIZE > EFI_PAGE_SIZE &&
|
if (PAGE_SIZE > EFI_PAGE_SIZE &&
|
||||||
(!PAGE_ALIGNED(in->phys_addr) ||
|
(!PAGE_ALIGNED(in->phys_addr) ||
|
||||||
!PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) {
|
!PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) {
|
||||||
|
@ -337,7 +337,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
|
|||||||
{
|
{
|
||||||
struct amdgpu_ctx *ctx;
|
struct amdgpu_ctx *ctx;
|
||||||
struct amdgpu_ctx_mgr *mgr;
|
struct amdgpu_ctx_mgr *mgr;
|
||||||
unsigned long ras_counter;
|
|
||||||
|
|
||||||
if (!fpriv)
|
if (!fpriv)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -362,21 +361,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
|
|||||||
if (atomic_read(&ctx->guilty))
|
if (atomic_read(&ctx->guilty))
|
||||||
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;
|
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;
|
||||||
|
|
||||||
/*query ue count*/
|
|
||||||
ras_counter = amdgpu_ras_query_error_count(adev, false);
|
|
||||||
/*ras counter is monotonic increasing*/
|
|
||||||
if (ras_counter != ctx->ras_counter_ue) {
|
|
||||||
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_UE;
|
|
||||||
ctx->ras_counter_ue = ras_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*query ce count*/
|
|
||||||
ras_counter = amdgpu_ras_query_error_count(adev, true);
|
|
||||||
if (ras_counter != ctx->ras_counter_ce) {
|
|
||||||
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_CE;
|
|
||||||
ctx->ras_counter_ce = ras_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&mgr->lock);
|
mutex_unlock(&mgr->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -944,6 +944,7 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
|
|||||||
domains = amdgpu_display_supported_domains(drm_to_adev(dev), bo->flags);
|
domains = amdgpu_display_supported_domains(drm_to_adev(dev), bo->flags);
|
||||||
if (obj->import_attach && !(domains & AMDGPU_GEM_DOMAIN_GTT)) {
|
if (obj->import_attach && !(domains & AMDGPU_GEM_DOMAIN_GTT)) {
|
||||||
drm_dbg_kms(dev, "Cannot create framebuffer from imported dma_buf\n");
|
drm_dbg_kms(dev, "Cannot create framebuffer from imported dma_buf\n");
|
||||||
|
drm_gem_object_put(obj);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,14 +187,14 @@ static int jpeg_v2_5_hw_init(void *handle)
|
|||||||
static int jpeg_v2_5_hw_fini(void *handle)
|
static int jpeg_v2_5_hw_fini(void *handle)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||||
struct amdgpu_ring *ring;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&adev->vcn.idle_work);
|
||||||
|
|
||||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||||
if (adev->jpeg.harvest_config & (1 << i))
|
if (adev->jpeg.harvest_config & (1 << i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ring = &adev->jpeg.inst[i].ring_dec;
|
|
||||||
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
|
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
|
||||||
RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS))
|
RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS))
|
||||||
jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
|
jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
|
||||||
|
@ -159,9 +159,9 @@ static int jpeg_v3_0_hw_init(void *handle)
|
|||||||
static int jpeg_v3_0_hw_fini(void *handle)
|
static int jpeg_v3_0_hw_fini(void *handle)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||||
struct amdgpu_ring *ring;
|
|
||||||
|
|
||||||
ring = &adev->jpeg.inst->ring_dec;
|
cancel_delayed_work_sync(&adev->vcn.idle_work);
|
||||||
|
|
||||||
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
|
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
|
||||||
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
|
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
|
||||||
jpeg_v3_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
|
jpeg_v3_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
|
||||||
|
@ -357,6 +357,7 @@ static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
dma_fence_put(fence);
|
dma_fence_put(fence);
|
||||||
|
amdgpu_bo_unpin(bo);
|
||||||
amdgpu_bo_unreserve(bo);
|
amdgpu_bo_unreserve(bo);
|
||||||
amdgpu_bo_unref(&bo);
|
amdgpu_bo_unref(&bo);
|
||||||
return r;
|
return r;
|
||||||
|
@ -367,15 +367,14 @@ static int vcn_v3_0_hw_init(void *handle)
|
|||||||
static int vcn_v3_0_hw_fini(void *handle)
|
static int vcn_v3_0_hw_fini(void *handle)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||||
struct amdgpu_ring *ring;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&adev->vcn.idle_work);
|
||||||
|
|
||||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||||
if (adev->vcn.harvest_config & (1 << i))
|
if (adev->vcn.harvest_config & (1 << i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ring = &adev->vcn.inst[i].ring_dec;
|
|
||||||
|
|
||||||
if (!amdgpu_sriov_vf(adev)) {
|
if (!amdgpu_sriov_vf(adev)) {
|
||||||
if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
|
if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
|
||||||
(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
|
(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
|
||||||
|
@ -1392,8 +1392,8 @@ static int live_breadcrumbs_smoketest(void *arg)
|
|||||||
|
|
||||||
for (n = 0; n < smoke[0].ncontexts; n++) {
|
for (n = 0; n < smoke[0].ncontexts; n++) {
|
||||||
smoke[0].contexts[n] = live_context(i915, file);
|
smoke[0].contexts[n] = live_context(i915, file);
|
||||||
if (!smoke[0].contexts[n]) {
|
if (IS_ERR(smoke[0].contexts[n])) {
|
||||||
ret = -ENOMEM;
|
ret = PTR_ERR(smoke[0].contexts[n]);
|
||||||
goto out_contexts;
|
goto out_contexts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -933,8 +933,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
|
|||||||
DPU_DEBUG("REG_DMA is not defined");
|
DPU_DEBUG("REG_DMA is not defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss"))
|
dpu_kms_parse_data_bus_icc_path(dpu_kms);
|
||||||
dpu_kms_parse_data_bus_icc_path(dpu_kms);
|
|
||||||
|
|
||||||
pm_runtime_get_sync(&dpu_kms->pdev->dev);
|
pm_runtime_get_sync(&dpu_kms->pdev->dev);
|
||||||
|
|
||||||
|
@ -31,40 +31,8 @@ struct dpu_mdss {
|
|||||||
void __iomem *mmio;
|
void __iomem *mmio;
|
||||||
struct dss_module_power mp;
|
struct dss_module_power mp;
|
||||||
struct dpu_irq_controller irq_controller;
|
struct dpu_irq_controller irq_controller;
|
||||||
struct icc_path *path[2];
|
|
||||||
u32 num_paths;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dpu_mdss_parse_data_bus_icc_path(struct drm_device *dev,
|
|
||||||
struct dpu_mdss *dpu_mdss)
|
|
||||||
{
|
|
||||||
struct icc_path *path0 = of_icc_get(dev->dev, "mdp0-mem");
|
|
||||||
struct icc_path *path1 = of_icc_get(dev->dev, "mdp1-mem");
|
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(path0))
|
|
||||||
return PTR_ERR_OR_ZERO(path0);
|
|
||||||
|
|
||||||
dpu_mdss->path[0] = path0;
|
|
||||||
dpu_mdss->num_paths = 1;
|
|
||||||
|
|
||||||
if (!IS_ERR_OR_NULL(path1)) {
|
|
||||||
dpu_mdss->path[1] = path1;
|
|
||||||
dpu_mdss->num_paths++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dpu_mdss_icc_request_bw(struct msm_mdss *mdss)
|
|
||||||
{
|
|
||||||
struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
|
|
||||||
int i;
|
|
||||||
u64 avg_bw = dpu_mdss->num_paths ? MAX_BW / dpu_mdss->num_paths : 0;
|
|
||||||
|
|
||||||
for (i = 0; i < dpu_mdss->num_paths; i++)
|
|
||||||
icc_set_bw(dpu_mdss->path[i], avg_bw, kBps_to_icc(MAX_BW));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dpu_mdss_irq(struct irq_desc *desc)
|
static void dpu_mdss_irq(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
struct dpu_mdss *dpu_mdss = irq_desc_get_handler_data(desc);
|
struct dpu_mdss *dpu_mdss = irq_desc_get_handler_data(desc);
|
||||||
@ -178,8 +146,6 @@ static int dpu_mdss_enable(struct msm_mdss *mdss)
|
|||||||
struct dss_module_power *mp = &dpu_mdss->mp;
|
struct dss_module_power *mp = &dpu_mdss->mp;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dpu_mdss_icc_request_bw(mdss);
|
|
||||||
|
|
||||||
ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
|
ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DPU_ERROR("clock enable failed, ret:%d\n", ret);
|
DPU_ERROR("clock enable failed, ret:%d\n", ret);
|
||||||
@ -213,15 +179,12 @@ static int dpu_mdss_disable(struct msm_mdss *mdss)
|
|||||||
{
|
{
|
||||||
struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
|
struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
|
||||||
struct dss_module_power *mp = &dpu_mdss->mp;
|
struct dss_module_power *mp = &dpu_mdss->mp;
|
||||||
int ret, i;
|
int ret;
|
||||||
|
|
||||||
ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
|
ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
DPU_ERROR("clock disable failed, ret:%d\n", ret);
|
DPU_ERROR("clock disable failed, ret:%d\n", ret);
|
||||||
|
|
||||||
for (i = 0; i < dpu_mdss->num_paths; i++)
|
|
||||||
icc_set_bw(dpu_mdss->path[i], 0, 0);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +195,6 @@ static void dpu_mdss_destroy(struct drm_device *dev)
|
|||||||
struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss);
|
struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss);
|
||||||
struct dss_module_power *mp = &dpu_mdss->mp;
|
struct dss_module_power *mp = &dpu_mdss->mp;
|
||||||
int irq;
|
int irq;
|
||||||
int i;
|
|
||||||
|
|
||||||
pm_runtime_suspend(dev->dev);
|
pm_runtime_suspend(dev->dev);
|
||||||
pm_runtime_disable(dev->dev);
|
pm_runtime_disable(dev->dev);
|
||||||
@ -242,9 +204,6 @@ static void dpu_mdss_destroy(struct drm_device *dev)
|
|||||||
msm_dss_put_clk(mp->clk_config, mp->num_clk);
|
msm_dss_put_clk(mp->clk_config, mp->num_clk);
|
||||||
devm_kfree(&pdev->dev, mp->clk_config);
|
devm_kfree(&pdev->dev, mp->clk_config);
|
||||||
|
|
||||||
for (i = 0; i < dpu_mdss->num_paths; i++)
|
|
||||||
icc_put(dpu_mdss->path[i]);
|
|
||||||
|
|
||||||
if (dpu_mdss->mmio)
|
if (dpu_mdss->mmio)
|
||||||
devm_iounmap(&pdev->dev, dpu_mdss->mmio);
|
devm_iounmap(&pdev->dev, dpu_mdss->mmio);
|
||||||
dpu_mdss->mmio = NULL;
|
dpu_mdss->mmio = NULL;
|
||||||
@ -276,12 +235,6 @@ int dpu_mdss_init(struct drm_device *dev)
|
|||||||
|
|
||||||
DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio);
|
DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio);
|
||||||
|
|
||||||
if (!of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) {
|
|
||||||
ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
mp = &dpu_mdss->mp;
|
mp = &dpu_mdss->mp;
|
||||||
ret = msm_dss_parse_clock(pdev, mp);
|
ret = msm_dss_parse_clock(pdev, mp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -307,8 +260,6 @@ int dpu_mdss_init(struct drm_device *dev)
|
|||||||
|
|
||||||
pm_runtime_enable(dev->dev);
|
pm_runtime_enable(dev->dev);
|
||||||
|
|
||||||
dpu_mdss_icc_request_bw(priv->mdss);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
irq_error:
|
irq_error:
|
||||||
|
@ -88,6 +88,7 @@ static void amd_sfh_work(struct work_struct *work)
|
|||||||
sensor_index = req_node->sensor_idx;
|
sensor_index = req_node->sensor_idx;
|
||||||
report_id = req_node->report_id;
|
report_id = req_node->report_id;
|
||||||
node_type = req_node->report_type;
|
node_type = req_node->report_type;
|
||||||
|
kfree(req_node);
|
||||||
|
|
||||||
if (node_type == HID_FEATURE_REPORT) {
|
if (node_type == HID_FEATURE_REPORT) {
|
||||||
report_size = get_feature_report(sensor_index, report_id,
|
report_size = get_feature_report(sensor_index, report_id,
|
||||||
|
@ -1262,6 +1262,7 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage,
|
|||||||
int status;
|
int status;
|
||||||
|
|
||||||
long flags = (long) data[2];
|
long flags = (long) data[2];
|
||||||
|
*level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
|
||||||
|
|
||||||
if (flags & 0x80)
|
if (flags & 0x80)
|
||||||
switch (flags & 0x07) {
|
switch (flags & 0x07) {
|
||||||
|
@ -597,7 +597,7 @@ static int magicmouse_probe(struct hid_device *hdev,
|
|||||||
if (id->vendor == USB_VENDOR_ID_APPLE &&
|
if (id->vendor == USB_VENDOR_ID_APPLE &&
|
||||||
id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
|
id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
|
||||||
hdev->type != HID_TYPE_USBMOUSE)
|
hdev->type != HID_TYPE_USBMOUSE)
|
||||||
return 0;
|
return -ENODEV;
|
||||||
|
|
||||||
msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
|
msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
|
||||||
if (msc == NULL) {
|
if (msc == NULL) {
|
||||||
|
@ -604,9 +604,13 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
|
|||||||
if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
|
if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (n = 0; n < field->report_count; n++) {
|
if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) {
|
||||||
if (field->usage[n].hid == HID_DG_CONTACTID)
|
for (n = 0; n < field->report_count; n++) {
|
||||||
rdata->is_mt_collection = true;
|
if (field->usage[n].hid == HID_DG_CONTACTID) {
|
||||||
|
rdata->is_mt_collection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#define I2C_HID_QUIRK_BOGUS_IRQ BIT(4)
|
#define I2C_HID_QUIRK_BOGUS_IRQ BIT(4)
|
||||||
#define I2C_HID_QUIRK_RESET_ON_RESUME BIT(5)
|
#define I2C_HID_QUIRK_RESET_ON_RESUME BIT(5)
|
||||||
#define I2C_HID_QUIRK_BAD_INPUT_SIZE BIT(6)
|
#define I2C_HID_QUIRK_BAD_INPUT_SIZE BIT(6)
|
||||||
|
#define I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET BIT(7)
|
||||||
|
|
||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
@ -178,6 +179,11 @@ static const struct i2c_hid_quirks {
|
|||||||
I2C_HID_QUIRK_RESET_ON_RESUME },
|
I2C_HID_QUIRK_RESET_ON_RESUME },
|
||||||
{ USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
|
{ USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
|
||||||
I2C_HID_QUIRK_BAD_INPUT_SIZE },
|
I2C_HID_QUIRK_BAD_INPUT_SIZE },
|
||||||
|
/*
|
||||||
|
* Sending the wakeup after reset actually break ELAN touchscreen controller
|
||||||
|
*/
|
||||||
|
{ USB_VENDOR_ID_ELAN, HID_ANY_ID,
|
||||||
|
I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -461,7 +467,8 @@ static int i2c_hid_hwreset(struct i2c_client *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* At least some SIS devices need this after reset */
|
/* At least some SIS devices need this after reset */
|
||||||
ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
|
if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET))
|
||||||
|
ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&ihid->reset_lock);
|
mutex_unlock(&ihid->reset_lock);
|
||||||
@ -990,8 +997,8 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
|
|||||||
hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
|
hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
|
||||||
hid->product = le16_to_cpu(ihid->hdesc.wProductID);
|
hid->product = le16_to_cpu(ihid->hdesc.wProductID);
|
||||||
|
|
||||||
snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX",
|
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
|
||||||
client->name, hid->vendor, hid->product);
|
client->name, (u16)hid->vendor, (u16)hid->product);
|
||||||
strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
|
strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
|
||||||
|
|
||||||
ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
|
ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
|
||||||
|
@ -1292,6 +1292,7 @@ int hid_pidff_init(struct hid_device *hid)
|
|||||||
|
|
||||||
if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
|
if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
|
||||||
pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
|
pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
|
||||||
|
error = -EPERM;
|
||||||
hid_notice(hid,
|
hid_notice(hid,
|
||||||
"device does not support device managed pool\n");
|
"device does not support device managed pool\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -838,10 +838,10 @@ static struct attribute *i8k_attrs[] = {
|
|||||||
static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
|
static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
if (disallow_fan_support && index >= 8)
|
if (disallow_fan_support && index >= 20)
|
||||||
return 0;
|
return 0;
|
||||||
if (disallow_fan_type_call &&
|
if (disallow_fan_type_call &&
|
||||||
(index == 9 || index == 12 || index == 15))
|
(index == 21 || index == 25 || index == 28))
|
||||||
return 0;
|
return 0;
|
||||||
if (index >= 0 && index <= 1 &&
|
if (index >= 0 && index <= 1 &&
|
||||||
!(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
|
!(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
|
||||||
|
@ -244,8 +244,8 @@ static int isl68137_probe(struct i2c_client *client)
|
|||||||
info->read_word_data = raa_dmpvr2_read_word_data;
|
info->read_word_data = raa_dmpvr2_read_word_data;
|
||||||
break;
|
break;
|
||||||
case raa_dmpvr2_2rail_nontc:
|
case raa_dmpvr2_2rail_nontc:
|
||||||
info->func[0] &= ~PMBUS_HAVE_TEMP;
|
info->func[0] &= ~PMBUS_HAVE_TEMP3;
|
||||||
info->func[1] &= ~PMBUS_HAVE_TEMP;
|
info->func[1] &= ~PMBUS_HAVE_TEMP3;
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case raa_dmpvr2_2rail:
|
case raa_dmpvr2_2rail:
|
||||||
info->pages = 2;
|
info->pages = 2;
|
||||||
|
@ -650,6 +650,14 @@ static int geni_i2c_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void geni_i2c_shutdown(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
/* Make client i2c transfers start failing */
|
||||||
|
i2c_mark_adapter_suspended(&gi2c->adap);
|
||||||
|
}
|
||||||
|
|
||||||
static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
|
static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -690,6 +698,8 @@ static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
|
struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
i2c_mark_adapter_suspended(&gi2c->adap);
|
||||||
|
|
||||||
if (!gi2c->suspended) {
|
if (!gi2c->suspended) {
|
||||||
geni_i2c_runtime_suspend(dev);
|
geni_i2c_runtime_suspend(dev);
|
||||||
pm_runtime_disable(dev);
|
pm_runtime_disable(dev);
|
||||||
@ -699,8 +709,16 @@ static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused geni_i2c_resume_noirq(struct device *dev)
|
||||||
|
{
|
||||||
|
struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
i2c_mark_adapter_resumed(&gi2c->adap);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops geni_i2c_pm_ops = {
|
static const struct dev_pm_ops geni_i2c_pm_ops = {
|
||||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(geni_i2c_suspend_noirq, NULL)
|
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(geni_i2c_suspend_noirq, geni_i2c_resume_noirq)
|
||||||
SET_RUNTIME_PM_OPS(geni_i2c_runtime_suspend, geni_i2c_runtime_resume,
|
SET_RUNTIME_PM_OPS(geni_i2c_runtime_suspend, geni_i2c_runtime_resume,
|
||||||
NULL)
|
NULL)
|
||||||
};
|
};
|
||||||
@ -714,6 +732,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
|
|||||||
static struct platform_driver geni_i2c_driver = {
|
static struct platform_driver geni_i2c_driver = {
|
||||||
.probe = geni_i2c_probe,
|
.probe = geni_i2c_probe,
|
||||||
.remove = geni_i2c_remove,
|
.remove = geni_i2c_remove,
|
||||||
|
.shutdown = geni_i2c_shutdown,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "geni_i2c",
|
.name = "geni_i2c",
|
||||||
.pm = &geni_i2c_pm_ops,
|
.pm = &geni_i2c_pm_ops,
|
||||||
|
@ -1282,7 +1282,7 @@ static void imx477_adjust_exposure_range(struct imx477 *imx477)
|
|||||||
|
|
||||||
/* Honour the VBLANK limits when setting exposure. */
|
/* Honour the VBLANK limits when setting exposure. */
|
||||||
exposure_max = imx477->mode->height + imx477->vblank->val -
|
exposure_max = imx477->mode->height + imx477->vblank->val -
|
||||||
(IMX477_EXPOSURE_OFFSET << imx477->long_exp_shift);
|
IMX477_EXPOSURE_OFFSET;
|
||||||
exposure_def = min(exposure_max, imx477->exposure->val);
|
exposure_def = min(exposure_max, imx477->exposure->val);
|
||||||
__v4l2_ctrl_modify_range(imx477->exposure, imx477->exposure->minimum,
|
__v4l2_ctrl_modify_range(imx477->exposure, imx477->exposure->minimum,
|
||||||
exposure_max, imx477->exposure->step,
|
exposure_max, imx477->exposure->step,
|
||||||
|
@ -2177,8 +2177,6 @@ int cxgb4_update_mac_filt(struct port_info *pi, unsigned int viid,
|
|||||||
bool persistent, u8 *smt_idx);
|
bool persistent, u8 *smt_idx);
|
||||||
int cxgb4_get_msix_idx_from_bmap(struct adapter *adap);
|
int cxgb4_get_msix_idx_from_bmap(struct adapter *adap);
|
||||||
void cxgb4_free_msix_idx_in_bmap(struct adapter *adap, u32 msix_idx);
|
void cxgb4_free_msix_idx_in_bmap(struct adapter *adap, u32 msix_idx);
|
||||||
int cxgb_open(struct net_device *dev);
|
|
||||||
int cxgb_close(struct net_device *dev);
|
|
||||||
void cxgb4_enable_rx(struct adapter *adap, struct sge_rspq *q);
|
void cxgb4_enable_rx(struct adapter *adap, struct sge_rspq *q);
|
||||||
void cxgb4_quiesce_rx(struct sge_rspq *q);
|
void cxgb4_quiesce_rx(struct sge_rspq *q);
|
||||||
int cxgb4_port_mirror_alloc(struct net_device *dev);
|
int cxgb4_port_mirror_alloc(struct net_device *dev);
|
||||||
|
@ -2834,7 +2834,7 @@ static void cxgb_down(struct adapter *adapter)
|
|||||||
/*
|
/*
|
||||||
* net_device operations
|
* net_device operations
|
||||||
*/
|
*/
|
||||||
int cxgb_open(struct net_device *dev)
|
static int cxgb_open(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct port_info *pi = netdev_priv(dev);
|
struct port_info *pi = netdev_priv(dev);
|
||||||
struct adapter *adapter = pi->adapter;
|
struct adapter *adapter = pi->adapter;
|
||||||
@ -2882,7 +2882,7 @@ int cxgb_open(struct net_device *dev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cxgb_close(struct net_device *dev)
|
static int cxgb_close(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct port_info *pi = netdev_priv(dev);
|
struct port_info *pi = netdev_priv(dev);
|
||||||
struct adapter *adapter = pi->adapter;
|
struct adapter *adapter = pi->adapter;
|
||||||
|
@ -997,20 +997,16 @@ int cxgb4_tc_flower_destroy(struct net_device *dev,
|
|||||||
if (!ch_flower)
|
if (!ch_flower)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
rhashtable_remove_fast(&adap->flower_tbl, &ch_flower->node,
|
||||||
|
adap->flower_ht_params);
|
||||||
|
|
||||||
ret = cxgb4_flow_rule_destroy(dev, ch_flower->fs.tc_prio,
|
ret = cxgb4_flow_rule_destroy(dev, ch_flower->fs.tc_prio,
|
||||||
&ch_flower->fs, ch_flower->filter_id);
|
&ch_flower->fs, ch_flower->filter_id);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
netdev_err(dev, "Flow rule destroy failed for tid: %u, ret: %d",
|
||||||
|
ch_flower->filter_id, ret);
|
||||||
|
|
||||||
ret = rhashtable_remove_fast(&adap->flower_tbl, &ch_flower->node,
|
|
||||||
adap->flower_ht_params);
|
|
||||||
if (ret) {
|
|
||||||
netdev_err(dev, "Flow remove from rhashtable failed");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
kfree_rcu(ch_flower, rcu);
|
kfree_rcu(ch_flower, rcu);
|
||||||
|
|
||||||
err:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,7 +589,8 @@ int cxgb4_setup_tc_mqprio(struct net_device *dev,
|
|||||||
* down before configuring tc params.
|
* down before configuring tc params.
|
||||||
*/
|
*/
|
||||||
if (netif_running(dev)) {
|
if (netif_running(dev)) {
|
||||||
cxgb_close(dev);
|
netif_tx_stop_all_queues(dev);
|
||||||
|
netif_carrier_off(dev);
|
||||||
needs_bring_up = true;
|
needs_bring_up = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,8 +616,10 @@ int cxgb4_setup_tc_mqprio(struct net_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (needs_bring_up)
|
if (needs_bring_up) {
|
||||||
cxgb_open(dev);
|
netif_tx_start_all_queues(dev);
|
||||||
|
netif_carrier_on(dev);
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&adap->tc_mqprio->mqprio_mutex);
|
mutex_unlock(&adap->tc_mqprio->mqprio_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2556,6 +2556,12 @@ int cxgb4_ethofld_send_flowc(struct net_device *dev, u32 eotid, u32 tc)
|
|||||||
if (!eosw_txq)
|
if (!eosw_txq)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (!(adap->flags & CXGB4_FW_OK)) {
|
||||||
|
/* Don't stall caller when access to FW is lost */
|
||||||
|
complete(&eosw_txq->completion);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
skb = alloc_skb(len, GFP_KERNEL);
|
skb = alloc_skb(len, GFP_KERNEL);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -2313,15 +2313,20 @@ static int i40e_run_xdp(struct i40e_ring *rx_ring, struct xdp_buff *xdp)
|
|||||||
case XDP_TX:
|
case XDP_TX:
|
||||||
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
|
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
|
||||||
result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);
|
result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);
|
||||||
|
if (result == I40E_XDP_CONSUMED)
|
||||||
|
goto out_failure;
|
||||||
break;
|
break;
|
||||||
case XDP_REDIRECT:
|
case XDP_REDIRECT:
|
||||||
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
||||||
result = !err ? I40E_XDP_REDIR : I40E_XDP_CONSUMED;
|
if (err)
|
||||||
|
goto out_failure;
|
||||||
|
result = I40E_XDP_REDIR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bpf_warn_invalid_xdp_action(act);
|
bpf_warn_invalid_xdp_action(act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_ABORTED:
|
case XDP_ABORTED:
|
||||||
|
out_failure:
|
||||||
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
||||||
fallthrough; /* handle aborts by dropping packet */
|
fallthrough; /* handle aborts by dropping packet */
|
||||||
case XDP_DROP:
|
case XDP_DROP:
|
||||||
|
@ -160,21 +160,28 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp)
|
|||||||
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
|
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
|
||||||
act = bpf_prog_run_xdp(xdp_prog, xdp);
|
act = bpf_prog_run_xdp(xdp_prog, xdp);
|
||||||
|
|
||||||
|
if (likely(act == XDP_REDIRECT)) {
|
||||||
|
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
||||||
|
if (err)
|
||||||
|
goto out_failure;
|
||||||
|
rcu_read_unlock();
|
||||||
|
return I40E_XDP_REDIR;
|
||||||
|
}
|
||||||
|
|
||||||
switch (act) {
|
switch (act) {
|
||||||
case XDP_PASS:
|
case XDP_PASS:
|
||||||
break;
|
break;
|
||||||
case XDP_TX:
|
case XDP_TX:
|
||||||
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
|
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
|
||||||
result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);
|
result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);
|
||||||
break;
|
if (result == I40E_XDP_CONSUMED)
|
||||||
case XDP_REDIRECT:
|
goto out_failure;
|
||||||
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
|
||||||
result = !err ? I40E_XDP_REDIR : I40E_XDP_CONSUMED;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bpf_warn_invalid_xdp_action(act);
|
bpf_warn_invalid_xdp_action(act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_ABORTED:
|
case XDP_ABORTED:
|
||||||
|
out_failure:
|
||||||
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
||||||
fallthrough; /* handle aborts by dropping packet */
|
fallthrough; /* handle aborts by dropping packet */
|
||||||
case XDP_DROP:
|
case XDP_DROP:
|
||||||
|
@ -325,6 +325,7 @@ struct ice_vsi {
|
|||||||
struct ice_tc_cfg tc_cfg;
|
struct ice_tc_cfg tc_cfg;
|
||||||
struct bpf_prog *xdp_prog;
|
struct bpf_prog *xdp_prog;
|
||||||
struct ice_ring **xdp_rings; /* XDP ring array */
|
struct ice_ring **xdp_rings; /* XDP ring array */
|
||||||
|
unsigned long *af_xdp_zc_qps; /* tracks AF_XDP ZC enabled qps */
|
||||||
u16 num_xdp_txq; /* Used XDP queues */
|
u16 num_xdp_txq; /* Used XDP queues */
|
||||||
u8 xdp_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
|
u8 xdp_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
|
||||||
|
|
||||||
@ -534,15 +535,16 @@ static inline void ice_set_ring_xdp(struct ice_ring *ring)
|
|||||||
*/
|
*/
|
||||||
static inline struct xsk_buff_pool *ice_xsk_pool(struct ice_ring *ring)
|
static inline struct xsk_buff_pool *ice_xsk_pool(struct ice_ring *ring)
|
||||||
{
|
{
|
||||||
|
struct ice_vsi *vsi = ring->vsi;
|
||||||
u16 qid = ring->q_index;
|
u16 qid = ring->q_index;
|
||||||
|
|
||||||
if (ice_ring_is_xdp(ring))
|
if (ice_ring_is_xdp(ring))
|
||||||
qid -= ring->vsi->num_xdp_txq;
|
qid -= vsi->num_xdp_txq;
|
||||||
|
|
||||||
if (!ice_is_xdp_ena_vsi(ring->vsi))
|
if (!ice_is_xdp_ena_vsi(vsi) || !test_bit(qid, vsi->af_xdp_zc_qps))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return xsk_get_pool_from_qid(ring->vsi->netdev, qid);
|
return xsk_get_pool_from_qid(vsi->netdev, qid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1797,49 +1797,6 @@ ice_phy_type_to_ethtool(struct net_device *netdev,
|
|||||||
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
|
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
|
||||||
100000baseKR4_Full);
|
100000baseKR4_Full);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Autoneg PHY types */
|
|
||||||
if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) {
|
|
||||||
ethtool_link_ksettings_add_link_mode(ks, supported,
|
|
||||||
Autoneg);
|
|
||||||
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
|
||||||
Autoneg);
|
|
||||||
}
|
|
||||||
if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) {
|
|
||||||
ethtool_link_ksettings_add_link_mode(ks, supported,
|
|
||||||
Autoneg);
|
|
||||||
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
|
||||||
Autoneg);
|
|
||||||
}
|
|
||||||
if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 ||
|
|
||||||
phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) {
|
|
||||||
ethtool_link_ksettings_add_link_mode(ks, supported,
|
|
||||||
Autoneg);
|
|
||||||
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
|
||||||
Autoneg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_SET_BITS_TIMEOUT 50
|
#define TEST_SET_BITS_TIMEOUT 50
|
||||||
@ -1996,9 +1953,7 @@ ice_get_link_ksettings(struct net_device *netdev,
|
|||||||
ks->base.port = PORT_TP;
|
ks->base.port = PORT_TP;
|
||||||
break;
|
break;
|
||||||
case ICE_MEDIA_BACKPLANE:
|
case ICE_MEDIA_BACKPLANE:
|
||||||
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
|
|
||||||
ethtool_link_ksettings_add_link_mode(ks, supported, Backplane);
|
ethtool_link_ksettings_add_link_mode(ks, supported, Backplane);
|
||||||
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
|
|
||||||
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
||||||
Backplane);
|
Backplane);
|
||||||
ks->base.port = PORT_NONE;
|
ks->base.port = PORT_NONE;
|
||||||
@ -2073,6 +2028,12 @@ ice_get_link_ksettings(struct net_device *netdev,
|
|||||||
if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN)
|
if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN)
|
||||||
ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
|
ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
|
||||||
|
|
||||||
|
/* Set supported and advertised autoneg */
|
||||||
|
if (ice_is_phy_caps_an_enabled(caps)) {
|
||||||
|
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
|
||||||
|
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
kfree(caps);
|
kfree(caps);
|
||||||
return err;
|
return err;
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#define PF_FW_ATQLEN_ATQOVFL_M BIT(29)
|
#define PF_FW_ATQLEN_ATQOVFL_M BIT(29)
|
||||||
#define PF_FW_ATQLEN_ATQCRIT_M BIT(30)
|
#define PF_FW_ATQLEN_ATQCRIT_M BIT(30)
|
||||||
#define VF_MBX_ARQLEN(_VF) (0x0022BC00 + ((_VF) * 4))
|
#define VF_MBX_ARQLEN(_VF) (0x0022BC00 + ((_VF) * 4))
|
||||||
|
#define VF_MBX_ATQLEN(_VF) (0x0022A800 + ((_VF) * 4))
|
||||||
#define PF_FW_ATQLEN_ATQENABLE_M BIT(31)
|
#define PF_FW_ATQLEN_ATQENABLE_M BIT(31)
|
||||||
#define PF_FW_ATQT 0x00080400
|
#define PF_FW_ATQT 0x00080400
|
||||||
#define PF_MBX_ARQBAH 0x0022E400
|
#define PF_MBX_ARQBAH 0x0022E400
|
||||||
|
@ -105,8 +105,14 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi)
|
|||||||
if (!vsi->q_vectors)
|
if (!vsi->q_vectors)
|
||||||
goto err_vectors;
|
goto err_vectors;
|
||||||
|
|
||||||
|
vsi->af_xdp_zc_qps = bitmap_zalloc(max_t(int, vsi->alloc_txq, vsi->alloc_rxq), GFP_KERNEL);
|
||||||
|
if (!vsi->af_xdp_zc_qps)
|
||||||
|
goto err_zc_qps;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_zc_qps:
|
||||||
|
devm_kfree(dev, vsi->q_vectors);
|
||||||
err_vectors:
|
err_vectors:
|
||||||
devm_kfree(dev, vsi->rxq_map);
|
devm_kfree(dev, vsi->rxq_map);
|
||||||
err_rxq_map:
|
err_rxq_map:
|
||||||
@ -192,6 +198,8 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
|
|||||||
break;
|
break;
|
||||||
case ICE_VSI_VF:
|
case ICE_VSI_VF:
|
||||||
vf = &pf->vf[vsi->vf_id];
|
vf = &pf->vf[vsi->vf_id];
|
||||||
|
if (vf->num_req_qs)
|
||||||
|
vf->num_vf_qs = vf->num_req_qs;
|
||||||
vsi->alloc_txq = vf->num_vf_qs;
|
vsi->alloc_txq = vf->num_vf_qs;
|
||||||
vsi->alloc_rxq = vf->num_vf_qs;
|
vsi->alloc_rxq = vf->num_vf_qs;
|
||||||
/* pf->num_msix_per_vf includes (VF miscellaneous vector +
|
/* pf->num_msix_per_vf includes (VF miscellaneous vector +
|
||||||
@ -286,6 +294,10 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi)
|
|||||||
|
|
||||||
dev = ice_pf_to_dev(pf);
|
dev = ice_pf_to_dev(pf);
|
||||||
|
|
||||||
|
if (vsi->af_xdp_zc_qps) {
|
||||||
|
bitmap_free(vsi->af_xdp_zc_qps);
|
||||||
|
vsi->af_xdp_zc_qps = NULL;
|
||||||
|
}
|
||||||
/* free the ring and vector containers */
|
/* free the ring and vector containers */
|
||||||
if (vsi->q_vectors) {
|
if (vsi->q_vectors) {
|
||||||
devm_kfree(dev, vsi->q_vectors);
|
devm_kfree(dev, vsi->q_vectors);
|
||||||
|
@ -523,7 +523,7 @@ ice_run_xdp(struct ice_ring *rx_ring, struct xdp_buff *xdp,
|
|||||||
struct bpf_prog *xdp_prog)
|
struct bpf_prog *xdp_prog)
|
||||||
{
|
{
|
||||||
struct ice_ring *xdp_ring;
|
struct ice_ring *xdp_ring;
|
||||||
int err;
|
int err, result;
|
||||||
u32 act;
|
u32 act;
|
||||||
|
|
||||||
act = bpf_prog_run_xdp(xdp_prog, xdp);
|
act = bpf_prog_run_xdp(xdp_prog, xdp);
|
||||||
@ -532,14 +532,20 @@ ice_run_xdp(struct ice_ring *rx_ring, struct xdp_buff *xdp,
|
|||||||
return ICE_XDP_PASS;
|
return ICE_XDP_PASS;
|
||||||
case XDP_TX:
|
case XDP_TX:
|
||||||
xdp_ring = rx_ring->vsi->xdp_rings[smp_processor_id()];
|
xdp_ring = rx_ring->vsi->xdp_rings[smp_processor_id()];
|
||||||
return ice_xmit_xdp_buff(xdp, xdp_ring);
|
result = ice_xmit_xdp_buff(xdp, xdp_ring);
|
||||||
|
if (result == ICE_XDP_CONSUMED)
|
||||||
|
goto out_failure;
|
||||||
|
return result;
|
||||||
case XDP_REDIRECT:
|
case XDP_REDIRECT:
|
||||||
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
||||||
return !err ? ICE_XDP_REDIR : ICE_XDP_CONSUMED;
|
if (err)
|
||||||
|
goto out_failure;
|
||||||
|
return ICE_XDP_REDIR;
|
||||||
default:
|
default:
|
||||||
bpf_warn_invalid_xdp_action(act);
|
bpf_warn_invalid_xdp_action(act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_ABORTED:
|
case XDP_ABORTED:
|
||||||
|
out_failure:
|
||||||
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_DROP:
|
case XDP_DROP:
|
||||||
@ -2331,6 +2337,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring)
|
|||||||
struct ice_tx_offload_params offload = { 0 };
|
struct ice_tx_offload_params offload = { 0 };
|
||||||
struct ice_vsi *vsi = tx_ring->vsi;
|
struct ice_vsi *vsi = tx_ring->vsi;
|
||||||
struct ice_tx_buf *first;
|
struct ice_tx_buf *first;
|
||||||
|
struct ethhdr *eth;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
int tso, csum;
|
int tso, csum;
|
||||||
|
|
||||||
@ -2377,7 +2384,9 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring)
|
|||||||
goto out_drop;
|
goto out_drop;
|
||||||
|
|
||||||
/* allow CONTROL frames egress from main VSI if FW LLDP disabled */
|
/* allow CONTROL frames egress from main VSI if FW LLDP disabled */
|
||||||
if (unlikely(skb->priority == TC_PRIO_CONTROL &&
|
eth = (struct ethhdr *)skb_mac_header(skb);
|
||||||
|
if (unlikely((skb->priority == TC_PRIO_CONTROL ||
|
||||||
|
eth->h_proto == htons(ETH_P_LLDP)) &&
|
||||||
vsi->type == ICE_VSI_PF &&
|
vsi->type == ICE_VSI_PF &&
|
||||||
vsi->port_info->qos_cfg.is_sw_lldp))
|
vsi->port_info->qos_cfg.is_sw_lldp))
|
||||||
offload.cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX |
|
offload.cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX |
|
||||||
|
@ -435,13 +435,15 @@ static void ice_trigger_vf_reset(struct ice_vf *vf, bool is_vflr, bool is_pfr)
|
|||||||
*/
|
*/
|
||||||
clear_bit(ICE_VF_STATE_INIT, vf->vf_states);
|
clear_bit(ICE_VF_STATE_INIT, vf->vf_states);
|
||||||
|
|
||||||
/* VF_MBX_ARQLEN is cleared by PFR, so the driver needs to clear it
|
/* VF_MBX_ARQLEN and VF_MBX_ATQLEN are cleared by PFR, so the driver
|
||||||
* in the case of VFR. If this is done for PFR, it can mess up VF
|
* needs to clear them in the case of VFR/VFLR. If this is done for
|
||||||
* resets because the VF driver may already have started cleanup
|
* PFR, it can mess up VF resets because the VF driver may already
|
||||||
* by the time we get here.
|
* have started cleanup by the time we get here.
|
||||||
*/
|
*/
|
||||||
if (!is_pfr)
|
if (!is_pfr) {
|
||||||
wr32(hw, VF_MBX_ARQLEN(vf->vf_id), 0);
|
wr32(hw, VF_MBX_ARQLEN(vf->vf_id), 0);
|
||||||
|
wr32(hw, VF_MBX_ATQLEN(vf->vf_id), 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* In the case of a VFLR, the HW has already reset the VF and we
|
/* In the case of a VFLR, the HW has already reset the VF and we
|
||||||
* just need to clean up, so don't hit the VFRTRIG register.
|
* just need to clean up, so don't hit the VFRTRIG register.
|
||||||
@ -1375,7 +1377,12 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ice_vf_pre_vsi_rebuild(vf);
|
ice_vf_pre_vsi_rebuild(vf);
|
||||||
ice_vf_rebuild_vsi_with_release(vf);
|
|
||||||
|
if (ice_vf_rebuild_vsi_with_release(vf)) {
|
||||||
|
dev_err(dev, "Failed to release and setup the VF%u's VSI\n", vf->vf_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ice_vf_post_vsi_rebuild(vf);
|
ice_vf_post_vsi_rebuild(vf);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -273,6 +273,7 @@ static int ice_xsk_pool_disable(struct ice_vsi *vsi, u16 qid)
|
|||||||
if (!pool)
|
if (!pool)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
clear_bit(qid, vsi->af_xdp_zc_qps);
|
||||||
xsk_pool_dma_unmap(pool, ICE_RX_DMA_ATTR);
|
xsk_pool_dma_unmap(pool, ICE_RX_DMA_ATTR);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -303,6 +304,8 @@ ice_xsk_pool_enable(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
set_bit(qid, vsi->af_xdp_zc_qps);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,21 +476,29 @@ ice_run_xdp_zc(struct ice_ring *rx_ring, struct xdp_buff *xdp)
|
|||||||
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
|
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
|
||||||
|
|
||||||
act = bpf_prog_run_xdp(xdp_prog, xdp);
|
act = bpf_prog_run_xdp(xdp_prog, xdp);
|
||||||
|
|
||||||
|
if (likely(act == XDP_REDIRECT)) {
|
||||||
|
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
||||||
|
if (err)
|
||||||
|
goto out_failure;
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ICE_XDP_REDIR;
|
||||||
|
}
|
||||||
|
|
||||||
switch (act) {
|
switch (act) {
|
||||||
case XDP_PASS:
|
case XDP_PASS:
|
||||||
break;
|
break;
|
||||||
case XDP_TX:
|
case XDP_TX:
|
||||||
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->q_index];
|
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->q_index];
|
||||||
result = ice_xmit_xdp_buff(xdp, xdp_ring);
|
result = ice_xmit_xdp_buff(xdp, xdp_ring);
|
||||||
break;
|
if (result == ICE_XDP_CONSUMED)
|
||||||
case XDP_REDIRECT:
|
goto out_failure;
|
||||||
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
|
||||||
result = !err ? ICE_XDP_REDIR : ICE_XDP_CONSUMED;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bpf_warn_invalid_xdp_action(act);
|
bpf_warn_invalid_xdp_action(act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_ABORTED:
|
case XDP_ABORTED:
|
||||||
|
out_failure:
|
||||||
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_DROP:
|
case XDP_DROP:
|
||||||
|
@ -749,7 +749,7 @@ void igb_ptp_rx_hang(struct igb_adapter *adapter);
|
|||||||
void igb_ptp_tx_hang(struct igb_adapter *adapter);
|
void igb_ptp_tx_hang(struct igb_adapter *adapter);
|
||||||
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb);
|
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb);
|
||||||
int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
|
int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
|
||||||
struct sk_buff *skb);
|
ktime_t *timestamp);
|
||||||
int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||||
int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||||
void igb_set_flag_queue_pairs(struct igb_adapter *, const u32);
|
void igb_set_flag_queue_pairs(struct igb_adapter *, const u32);
|
||||||
|
@ -8281,7 +8281,7 @@ static void igb_add_rx_frag(struct igb_ring *rx_ring,
|
|||||||
static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring,
|
static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring,
|
||||||
struct igb_rx_buffer *rx_buffer,
|
struct igb_rx_buffer *rx_buffer,
|
||||||
struct xdp_buff *xdp,
|
struct xdp_buff *xdp,
|
||||||
union e1000_adv_rx_desc *rx_desc)
|
ktime_t timestamp)
|
||||||
{
|
{
|
||||||
#if (PAGE_SIZE < 8192)
|
#if (PAGE_SIZE < 8192)
|
||||||
unsigned int truesize = igb_rx_pg_size(rx_ring) / 2;
|
unsigned int truesize = igb_rx_pg_size(rx_ring) / 2;
|
||||||
@ -8301,12 +8301,8 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring,
|
|||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (unlikely(igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))) {
|
if (timestamp)
|
||||||
if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb)) {
|
skb_hwtstamps(skb)->hwtstamp = timestamp;
|
||||||
xdp->data += IGB_TS_HDR_LEN;
|
|
||||||
size -= IGB_TS_HDR_LEN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine available headroom for copy */
|
/* Determine available headroom for copy */
|
||||||
headlen = size;
|
headlen = size;
|
||||||
@ -8337,7 +8333,7 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring,
|
|||||||
static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,
|
static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,
|
||||||
struct igb_rx_buffer *rx_buffer,
|
struct igb_rx_buffer *rx_buffer,
|
||||||
struct xdp_buff *xdp,
|
struct xdp_buff *xdp,
|
||||||
union e1000_adv_rx_desc *rx_desc)
|
ktime_t timestamp)
|
||||||
{
|
{
|
||||||
#if (PAGE_SIZE < 8192)
|
#if (PAGE_SIZE < 8192)
|
||||||
unsigned int truesize = igb_rx_pg_size(rx_ring) / 2;
|
unsigned int truesize = igb_rx_pg_size(rx_ring) / 2;
|
||||||
@ -8364,11 +8360,8 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,
|
|||||||
if (metasize)
|
if (metasize)
|
||||||
skb_metadata_set(skb, metasize);
|
skb_metadata_set(skb, metasize);
|
||||||
|
|
||||||
/* pull timestamp out of packet data */
|
if (timestamp)
|
||||||
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
|
skb_hwtstamps(skb)->hwtstamp = timestamp;
|
||||||
if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb))
|
|
||||||
__skb_pull(skb, IGB_TS_HDR_LEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update buffer offset */
|
/* update buffer offset */
|
||||||
#if (PAGE_SIZE < 8192)
|
#if (PAGE_SIZE < 8192)
|
||||||
@ -8402,18 +8395,20 @@ static struct sk_buff *igb_run_xdp(struct igb_adapter *adapter,
|
|||||||
break;
|
break;
|
||||||
case XDP_TX:
|
case XDP_TX:
|
||||||
result = igb_xdp_xmit_back(adapter, xdp);
|
result = igb_xdp_xmit_back(adapter, xdp);
|
||||||
|
if (result == IGB_XDP_CONSUMED)
|
||||||
|
goto out_failure;
|
||||||
break;
|
break;
|
||||||
case XDP_REDIRECT:
|
case XDP_REDIRECT:
|
||||||
err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog);
|
err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog);
|
||||||
if (!err)
|
if (err)
|
||||||
result = IGB_XDP_REDIR;
|
goto out_failure;
|
||||||
else
|
result = IGB_XDP_REDIR;
|
||||||
result = IGB_XDP_CONSUMED;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bpf_warn_invalid_xdp_action(act);
|
bpf_warn_invalid_xdp_action(act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_ABORTED:
|
case XDP_ABORTED:
|
||||||
|
out_failure:
|
||||||
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_DROP:
|
case XDP_DROP:
|
||||||
@ -8683,7 +8678,10 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||||||
while (likely(total_packets < budget)) {
|
while (likely(total_packets < budget)) {
|
||||||
union e1000_adv_rx_desc *rx_desc;
|
union e1000_adv_rx_desc *rx_desc;
|
||||||
struct igb_rx_buffer *rx_buffer;
|
struct igb_rx_buffer *rx_buffer;
|
||||||
|
ktime_t timestamp = 0;
|
||||||
|
int pkt_offset = 0;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
void *pktbuf;
|
||||||
|
|
||||||
/* return some buffers to hardware, one at a time is too slow */
|
/* return some buffers to hardware, one at a time is too slow */
|
||||||
if (cleaned_count >= IGB_RX_BUFFER_WRITE) {
|
if (cleaned_count >= IGB_RX_BUFFER_WRITE) {
|
||||||
@ -8703,14 +8701,24 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||||||
dma_rmb();
|
dma_rmb();
|
||||||
|
|
||||||
rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt);
|
rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt);
|
||||||
|
pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;
|
||||||
|
|
||||||
|
/* pull rx packet timestamp if available and valid */
|
||||||
|
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
|
||||||
|
int ts_hdr_len;
|
||||||
|
|
||||||
|
ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector,
|
||||||
|
pktbuf, ×tamp);
|
||||||
|
|
||||||
|
pkt_offset += ts_hdr_len;
|
||||||
|
size -= ts_hdr_len;
|
||||||
|
}
|
||||||
|
|
||||||
/* retrieve a buffer from the ring */
|
/* retrieve a buffer from the ring */
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
unsigned int offset = igb_rx_offset(rx_ring);
|
unsigned char *hard_start = pktbuf - igb_rx_offset(rx_ring);
|
||||||
unsigned char *hard_start;
|
unsigned int offset = pkt_offset + igb_rx_offset(rx_ring);
|
||||||
|
|
||||||
hard_start = page_address(rx_buffer->page) +
|
|
||||||
rx_buffer->page_offset - offset;
|
|
||||||
xdp_prepare_buff(&xdp, hard_start, offset, size, true);
|
xdp_prepare_buff(&xdp, hard_start, offset, size, true);
|
||||||
#if (PAGE_SIZE > 4096)
|
#if (PAGE_SIZE > 4096)
|
||||||
/* At larger PAGE_SIZE, frame_sz depend on len size */
|
/* At larger PAGE_SIZE, frame_sz depend on len size */
|
||||||
@ -8733,10 +8741,11 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||||||
} else if (skb)
|
} else if (skb)
|
||||||
igb_add_rx_frag(rx_ring, rx_buffer, skb, size);
|
igb_add_rx_frag(rx_ring, rx_buffer, skb, size);
|
||||||
else if (ring_uses_build_skb(rx_ring))
|
else if (ring_uses_build_skb(rx_ring))
|
||||||
skb = igb_build_skb(rx_ring, rx_buffer, &xdp, rx_desc);
|
skb = igb_build_skb(rx_ring, rx_buffer, &xdp,
|
||||||
|
timestamp);
|
||||||
else
|
else
|
||||||
skb = igb_construct_skb(rx_ring, rx_buffer,
|
skb = igb_construct_skb(rx_ring, rx_buffer,
|
||||||
&xdp, rx_desc);
|
&xdp, timestamp);
|
||||||
|
|
||||||
/* exit if we failed to retrieve a buffer */
|
/* exit if we failed to retrieve a buffer */
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
|
@ -856,30 +856,28 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
|
|||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IGB_RET_PTP_DISABLED 1
|
|
||||||
#define IGB_RET_PTP_INVALID 2
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
|
* igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
|
||||||
* @q_vector: Pointer to interrupt specific structure
|
* @q_vector: Pointer to interrupt specific structure
|
||||||
* @va: Pointer to address containing Rx buffer
|
* @va: Pointer to address containing Rx buffer
|
||||||
* @skb: Buffer containing timestamp and packet
|
* @timestamp: Pointer where timestamp will be stored
|
||||||
*
|
*
|
||||||
* This function is meant to retrieve a timestamp from the first buffer of an
|
* This function is meant to retrieve a timestamp from the first buffer of an
|
||||||
* incoming frame. The value is stored in little endian format starting on
|
* incoming frame. The value is stored in little endian format starting on
|
||||||
* byte 8
|
* byte 8
|
||||||
*
|
*
|
||||||
* Returns: 0 if success, nonzero if failure
|
* Returns: The timestamp header length or 0 if not available
|
||||||
**/
|
**/
|
||||||
int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
|
int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
|
||||||
struct sk_buff *skb)
|
ktime_t *timestamp)
|
||||||
{
|
{
|
||||||
struct igb_adapter *adapter = q_vector->adapter;
|
struct igb_adapter *adapter = q_vector->adapter;
|
||||||
|
struct skb_shared_hwtstamps ts;
|
||||||
__le64 *regval = (__le64 *)va;
|
__le64 *regval = (__le64 *)va;
|
||||||
int adjust = 0;
|
int adjust = 0;
|
||||||
|
|
||||||
if (!(adapter->ptp_flags & IGB_PTP_ENABLED))
|
if (!(adapter->ptp_flags & IGB_PTP_ENABLED))
|
||||||
return IGB_RET_PTP_DISABLED;
|
return 0;
|
||||||
|
|
||||||
/* The timestamp is recorded in little endian format.
|
/* The timestamp is recorded in little endian format.
|
||||||
* DWORD: 0 1 2 3
|
* DWORD: 0 1 2 3
|
||||||
@ -888,10 +886,9 @@ int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
|
|||||||
|
|
||||||
/* check reserved dwords are zero, be/le doesn't matter for zero */
|
/* check reserved dwords are zero, be/le doesn't matter for zero */
|
||||||
if (regval[0])
|
if (regval[0])
|
||||||
return IGB_RET_PTP_INVALID;
|
return 0;
|
||||||
|
|
||||||
igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb),
|
igb_ptp_systim_to_hwtstamp(adapter, &ts, le64_to_cpu(regval[1]));
|
||||||
le64_to_cpu(regval[1]));
|
|
||||||
|
|
||||||
/* adjust timestamp for the RX latency based on link speed */
|
/* adjust timestamp for the RX latency based on link speed */
|
||||||
if (adapter->hw.mac.type == e1000_i210) {
|
if (adapter->hw.mac.type == e1000_i210) {
|
||||||
@ -907,10 +904,10 @@ int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
skb_hwtstamps(skb)->hwtstamp =
|
|
||||||
ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust);
|
|
||||||
|
|
||||||
return 0;
|
*timestamp = ktime_sub_ns(ts.hwtstamp, adjust);
|
||||||
|
|
||||||
|
return IGB_TS_HDR_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2213,23 +2213,23 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
|
|||||||
break;
|
break;
|
||||||
case XDP_TX:
|
case XDP_TX:
|
||||||
xdpf = xdp_convert_buff_to_frame(xdp);
|
xdpf = xdp_convert_buff_to_frame(xdp);
|
||||||
if (unlikely(!xdpf)) {
|
if (unlikely(!xdpf))
|
||||||
result = IXGBE_XDP_CONSUMED;
|
goto out_failure;
|
||||||
break;
|
|
||||||
}
|
|
||||||
result = ixgbe_xmit_xdp_ring(adapter, xdpf);
|
result = ixgbe_xmit_xdp_ring(adapter, xdpf);
|
||||||
|
if (result == IXGBE_XDP_CONSUMED)
|
||||||
|
goto out_failure;
|
||||||
break;
|
break;
|
||||||
case XDP_REDIRECT:
|
case XDP_REDIRECT:
|
||||||
err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog);
|
err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog);
|
||||||
if (!err)
|
if (err)
|
||||||
result = IXGBE_XDP_REDIR;
|
goto out_failure;
|
||||||
else
|
result = IXGBE_XDP_REDIR;
|
||||||
result = IXGBE_XDP_CONSUMED;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bpf_warn_invalid_xdp_action(act);
|
bpf_warn_invalid_xdp_action(act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_ABORTED:
|
case XDP_ABORTED:
|
||||||
|
out_failure:
|
||||||
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
||||||
fallthrough; /* handle aborts by dropping packet */
|
fallthrough; /* handle aborts by dropping packet */
|
||||||
case XDP_DROP:
|
case XDP_DROP:
|
||||||
|
@ -104,25 +104,30 @@ static int ixgbe_run_xdp_zc(struct ixgbe_adapter *adapter,
|
|||||||
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
|
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
|
||||||
act = bpf_prog_run_xdp(xdp_prog, xdp);
|
act = bpf_prog_run_xdp(xdp_prog, xdp);
|
||||||
|
|
||||||
|
if (likely(act == XDP_REDIRECT)) {
|
||||||
|
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
||||||
|
if (err)
|
||||||
|
goto out_failure;
|
||||||
|
rcu_read_unlock();
|
||||||
|
return IXGBE_XDP_REDIR;
|
||||||
|
}
|
||||||
|
|
||||||
switch (act) {
|
switch (act) {
|
||||||
case XDP_PASS:
|
case XDP_PASS:
|
||||||
break;
|
break;
|
||||||
case XDP_TX:
|
case XDP_TX:
|
||||||
xdpf = xdp_convert_buff_to_frame(xdp);
|
xdpf = xdp_convert_buff_to_frame(xdp);
|
||||||
if (unlikely(!xdpf)) {
|
if (unlikely(!xdpf))
|
||||||
result = IXGBE_XDP_CONSUMED;
|
goto out_failure;
|
||||||
break;
|
|
||||||
}
|
|
||||||
result = ixgbe_xmit_xdp_ring(adapter, xdpf);
|
result = ixgbe_xmit_xdp_ring(adapter, xdpf);
|
||||||
break;
|
if (result == IXGBE_XDP_CONSUMED)
|
||||||
case XDP_REDIRECT:
|
goto out_failure;
|
||||||
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
|
|
||||||
result = !err ? IXGBE_XDP_REDIR : IXGBE_XDP_CONSUMED;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bpf_warn_invalid_xdp_action(act);
|
bpf_warn_invalid_xdp_action(act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_ABORTED:
|
case XDP_ABORTED:
|
||||||
|
out_failure:
|
||||||
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
||||||
fallthrough; /* handle aborts by dropping packet */
|
fallthrough; /* handle aborts by dropping packet */
|
||||||
case XDP_DROP:
|
case XDP_DROP:
|
||||||
|
@ -1067,11 +1067,14 @@ static struct sk_buff *ixgbevf_run_xdp(struct ixgbevf_adapter *adapter,
|
|||||||
case XDP_TX:
|
case XDP_TX:
|
||||||
xdp_ring = adapter->xdp_ring[rx_ring->queue_index];
|
xdp_ring = adapter->xdp_ring[rx_ring->queue_index];
|
||||||
result = ixgbevf_xmit_xdp_ring(xdp_ring, xdp);
|
result = ixgbevf_xmit_xdp_ring(xdp_ring, xdp);
|
||||||
|
if (result == IXGBEVF_XDP_CONSUMED)
|
||||||
|
goto out_failure;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bpf_warn_invalid_xdp_action(act);
|
bpf_warn_invalid_xdp_action(act);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case XDP_ABORTED:
|
case XDP_ABORTED:
|
||||||
|
out_failure:
|
||||||
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
|
||||||
fallthrough; /* handle aborts by dropping packet */
|
fallthrough; /* handle aborts by dropping packet */
|
||||||
case XDP_DROP:
|
case XDP_DROP:
|
||||||
|
@ -1632,12 +1632,13 @@ static int mlx5e_set_fecparam(struct net_device *netdev,
|
|||||||
{
|
{
|
||||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||||
struct mlx5_core_dev *mdev = priv->mdev;
|
struct mlx5_core_dev *mdev = priv->mdev;
|
||||||
|
unsigned long fec_bitmap;
|
||||||
u16 fec_policy = 0;
|
u16 fec_policy = 0;
|
||||||
int mode;
|
int mode;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (bitmap_weight((unsigned long *)&fecparam->fec,
|
bitmap_from_arr32(&fec_bitmap, &fecparam->fec, sizeof(fecparam->fec) * BITS_PER_BYTE);
|
||||||
ETHTOOL_FEC_LLRS_BIT + 1) > 1)
|
if (bitmap_weight(&fec_bitmap, ETHTOOL_FEC_LLRS_BIT + 1) > 1)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
for (mode = 0; mode < ARRAY_SIZE(pplm_fec_2_ethtool); mode++) {
|
for (mode = 0; mode < ARRAY_SIZE(pplm_fec_2_ethtool); mode++) {
|
||||||
|
@ -1964,11 +1964,13 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
misc_parameters);
|
misc_parameters);
|
||||||
struct flow_rule *rule = flow_cls_offload_flow_rule(f);
|
struct flow_rule *rule = flow_cls_offload_flow_rule(f);
|
||||||
struct flow_dissector *dissector = rule->match.dissector;
|
struct flow_dissector *dissector = rule->match.dissector;
|
||||||
|
enum fs_flow_table_type fs_type;
|
||||||
u16 addr_type = 0;
|
u16 addr_type = 0;
|
||||||
u8 ip_proto = 0;
|
u8 ip_proto = 0;
|
||||||
u8 *match_level;
|
u8 *match_level;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
fs_type = mlx5e_is_eswitch_flow(flow) ? FS_FT_FDB : FS_FT_NIC_RX;
|
||||||
match_level = outer_match_level;
|
match_level = outer_match_level;
|
||||||
|
|
||||||
if (dissector->used_keys &
|
if (dissector->used_keys &
|
||||||
@ -2093,6 +2095,13 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
if (match.mask->vlan_id ||
|
if (match.mask->vlan_id ||
|
||||||
match.mask->vlan_priority ||
|
match.mask->vlan_priority ||
|
||||||
match.mask->vlan_tpid) {
|
match.mask->vlan_tpid) {
|
||||||
|
if (!MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, ft_field_support.outer_second_vid,
|
||||||
|
fs_type)) {
|
||||||
|
NL_SET_ERR_MSG_MOD(extack,
|
||||||
|
"Matching on CVLAN is not supported");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
if (match.key->vlan_tpid == htons(ETH_P_8021AD)) {
|
if (match.key->vlan_tpid == htons(ETH_P_8021AD)) {
|
||||||
MLX5_SET(fte_match_set_misc, misc_c,
|
MLX5_SET(fte_match_set_misc, misc_c,
|
||||||
outer_second_svlan_tag, 1);
|
outer_second_svlan_tag, 1);
|
||||||
|
@ -349,7 +349,8 @@ esw_setup_slow_path_dest(struct mlx5_flow_destination *dest,
|
|||||||
struct mlx5_fs_chains *chains,
|
struct mlx5_fs_chains *chains,
|
||||||
int i)
|
int i)
|
||||||
{
|
{
|
||||||
flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
|
if (mlx5_chains_ignore_flow_level_supported(chains))
|
||||||
|
flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
|
||||||
dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||||
dest[i].ft = mlx5_chains_get_tc_end_ft(chains);
|
dest[i].ft = mlx5_chains_get_tc_end_ft(chains);
|
||||||
}
|
}
|
||||||
|
@ -354,6 +354,9 @@ static void mlx5_sync_reset_abort_event(struct work_struct *work)
|
|||||||
reset_abort_work);
|
reset_abort_work);
|
||||||
struct mlx5_core_dev *dev = fw_reset->dev;
|
struct mlx5_core_dev *dev = fw_reset->dev;
|
||||||
|
|
||||||
|
if (!test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags))
|
||||||
|
return;
|
||||||
|
|
||||||
mlx5_sync_reset_clear_reset_requested(dev, true);
|
mlx5_sync_reset_clear_reset_requested(dev, true);
|
||||||
mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n");
|
mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n");
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ bool mlx5_chains_prios_supported(struct mlx5_fs_chains *chains)
|
|||||||
return chains->flags & MLX5_CHAINS_AND_PRIOS_SUPPORTED;
|
return chains->flags & MLX5_CHAINS_AND_PRIOS_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mlx5_chains_ignore_flow_level_supported(struct mlx5_fs_chains *chains)
|
bool mlx5_chains_ignore_flow_level_supported(struct mlx5_fs_chains *chains)
|
||||||
{
|
{
|
||||||
return chains->flags & MLX5_CHAINS_IGNORE_FLOW_LEVEL_SUPPORTED;
|
return chains->flags & MLX5_CHAINS_IGNORE_FLOW_LEVEL_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ struct mlx5_chains_attr {
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
mlx5_chains_prios_supported(struct mlx5_fs_chains *chains);
|
mlx5_chains_prios_supported(struct mlx5_fs_chains *chains);
|
||||||
|
bool mlx5_chains_ignore_flow_level_supported(struct mlx5_fs_chains *chains);
|
||||||
bool
|
bool
|
||||||
mlx5_chains_backwards_supported(struct mlx5_fs_chains *chains);
|
mlx5_chains_backwards_supported(struct mlx5_fs_chains *chains);
|
||||||
u32
|
u32
|
||||||
@ -72,6 +73,10 @@ mlx5_chains_set_end_ft(struct mlx5_fs_chains *chains,
|
|||||||
|
|
||||||
#else /* CONFIG_MLX5_CLS_ACT */
|
#else /* CONFIG_MLX5_CLS_ACT */
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
mlx5_chains_ignore_flow_level_supported(struct mlx5_fs_chains *chains)
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
static inline struct mlx5_flow_table *
|
static inline struct mlx5_flow_table *
|
||||||
mlx5_chains_get_table(struct mlx5_fs_chains *chains, u32 chain, u32 prio,
|
mlx5_chains_get_table(struct mlx5_fs_chains *chains, u32 chain, u32 prio,
|
||||||
u32 level) { return ERR_PTR(-EOPNOTSUPP); }
|
u32 level) { return ERR_PTR(-EOPNOTSUPP); }
|
||||||
|
@ -112,7 +112,8 @@ int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ft_attr.table_type = MLX5_FLOW_TABLE_TYPE_FDB;
|
ft_attr.table_type = MLX5_FLOW_TABLE_TYPE_FDB;
|
||||||
ft_attr.level = dmn->info.caps.max_ft_level - 2;
|
ft_attr.level = min_t(int, dmn->info.caps.max_ft_level - 2,
|
||||||
|
MLX5_FT_MAX_MULTIPATH_LEVEL);
|
||||||
ft_attr.reformat_en = reformat_req;
|
ft_attr.reformat_en = reformat_req;
|
||||||
ft_attr.decap_en = reformat_req;
|
ft_attr.decap_en = reformat_req;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
ccflags-y := -O3
|
ccflags-y := -D'pr_fmt(fmt)=KBUILD_MODNAME ": " fmt'
|
||||||
ccflags-y += -D'pr_fmt(fmt)=KBUILD_MODNAME ": " fmt'
|
|
||||||
ccflags-$(CONFIG_WIREGUARD_DEBUG) += -DDEBUG
|
ccflags-$(CONFIG_WIREGUARD_DEBUG) += -DDEBUG
|
||||||
wireguard-y := main.o
|
wireguard-y := main.o
|
||||||
wireguard-y += noise.o
|
wireguard-y += noise.o
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "allowedips.h"
|
#include "allowedips.h"
|
||||||
#include "peer.h"
|
#include "peer.h"
|
||||||
|
|
||||||
|
static struct kmem_cache *node_cache;
|
||||||
|
|
||||||
static void swap_endian(u8 *dst, const u8 *src, u8 bits)
|
static void swap_endian(u8 *dst, const u8 *src, u8 bits)
|
||||||
{
|
{
|
||||||
if (bits == 32) {
|
if (bits == 32) {
|
||||||
@ -28,8 +30,11 @@ static void copy_and_assign_cidr(struct allowedips_node *node, const u8 *src,
|
|||||||
node->bitlen = bits;
|
node->bitlen = bits;
|
||||||
memcpy(node->bits, src, bits / 8U);
|
memcpy(node->bits, src, bits / 8U);
|
||||||
}
|
}
|
||||||
#define CHOOSE_NODE(parent, key) \
|
|
||||||
parent->bit[(key[parent->bit_at_a] >> parent->bit_at_b) & 1]
|
static inline u8 choose(struct allowedips_node *node, const u8 *key)
|
||||||
|
{
|
||||||
|
return (key[node->bit_at_a] >> node->bit_at_b) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void push_rcu(struct allowedips_node **stack,
|
static void push_rcu(struct allowedips_node **stack,
|
||||||
struct allowedips_node __rcu *p, unsigned int *len)
|
struct allowedips_node __rcu *p, unsigned int *len)
|
||||||
@ -40,6 +45,11 @@ static void push_rcu(struct allowedips_node **stack,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void node_free_rcu(struct rcu_head *rcu)
|
||||||
|
{
|
||||||
|
kmem_cache_free(node_cache, container_of(rcu, struct allowedips_node, rcu));
|
||||||
|
}
|
||||||
|
|
||||||
static void root_free_rcu(struct rcu_head *rcu)
|
static void root_free_rcu(struct rcu_head *rcu)
|
||||||
{
|
{
|
||||||
struct allowedips_node *node, *stack[128] = {
|
struct allowedips_node *node, *stack[128] = {
|
||||||
@ -49,7 +59,7 @@ static void root_free_rcu(struct rcu_head *rcu)
|
|||||||
while (len > 0 && (node = stack[--len])) {
|
while (len > 0 && (node = stack[--len])) {
|
||||||
push_rcu(stack, node->bit[0], &len);
|
push_rcu(stack, node->bit[0], &len);
|
||||||
push_rcu(stack, node->bit[1], &len);
|
push_rcu(stack, node->bit[1], &len);
|
||||||
kfree(node);
|
kmem_cache_free(node_cache, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,60 +76,6 @@ static void root_remove_peer_lists(struct allowedips_node *root)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void walk_remove_by_peer(struct allowedips_node __rcu **top,
|
|
||||||
struct wg_peer *peer, struct mutex *lock)
|
|
||||||
{
|
|
||||||
#define REF(p) rcu_access_pointer(p)
|
|
||||||
#define DEREF(p) rcu_dereference_protected(*(p), lockdep_is_held(lock))
|
|
||||||
#define PUSH(p) ({ \
|
|
||||||
WARN_ON(IS_ENABLED(DEBUG) && len >= 128); \
|
|
||||||
stack[len++] = p; \
|
|
||||||
})
|
|
||||||
|
|
||||||
struct allowedips_node __rcu **stack[128], **nptr;
|
|
||||||
struct allowedips_node *node, *prev;
|
|
||||||
unsigned int len;
|
|
||||||
|
|
||||||
if (unlikely(!peer || !REF(*top)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (prev = NULL, len = 0, PUSH(top); len > 0; prev = node) {
|
|
||||||
nptr = stack[len - 1];
|
|
||||||
node = DEREF(nptr);
|
|
||||||
if (!node) {
|
|
||||||
--len;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!prev || REF(prev->bit[0]) == node ||
|
|
||||||
REF(prev->bit[1]) == node) {
|
|
||||||
if (REF(node->bit[0]))
|
|
||||||
PUSH(&node->bit[0]);
|
|
||||||
else if (REF(node->bit[1]))
|
|
||||||
PUSH(&node->bit[1]);
|
|
||||||
} else if (REF(node->bit[0]) == prev) {
|
|
||||||
if (REF(node->bit[1]))
|
|
||||||
PUSH(&node->bit[1]);
|
|
||||||
} else {
|
|
||||||
if (rcu_dereference_protected(node->peer,
|
|
||||||
lockdep_is_held(lock)) == peer) {
|
|
||||||
RCU_INIT_POINTER(node->peer, NULL);
|
|
||||||
list_del_init(&node->peer_list);
|
|
||||||
if (!node->bit[0] || !node->bit[1]) {
|
|
||||||
rcu_assign_pointer(*nptr, DEREF(
|
|
||||||
&node->bit[!REF(node->bit[0])]));
|
|
||||||
kfree_rcu(node, rcu);
|
|
||||||
node = DEREF(nptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef REF
|
|
||||||
#undef DEREF
|
|
||||||
#undef PUSH
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int fls128(u64 a, u64 b)
|
static unsigned int fls128(u64 a, u64 b)
|
||||||
{
|
{
|
||||||
return a ? fls64(a) + 64U : fls64(b);
|
return a ? fls64(a) + 64U : fls64(b);
|
||||||
@ -159,7 +115,7 @@ static struct allowedips_node *find_node(struct allowedips_node *trie, u8 bits,
|
|||||||
found = node;
|
found = node;
|
||||||
if (node->cidr == bits)
|
if (node->cidr == bits)
|
||||||
break;
|
break;
|
||||||
node = rcu_dereference_bh(CHOOSE_NODE(node, key));
|
node = rcu_dereference_bh(node->bit[choose(node, key)]);
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
@ -191,8 +147,7 @@ static bool node_placement(struct allowedips_node __rcu *trie, const u8 *key,
|
|||||||
u8 cidr, u8 bits, struct allowedips_node **rnode,
|
u8 cidr, u8 bits, struct allowedips_node **rnode,
|
||||||
struct mutex *lock)
|
struct mutex *lock)
|
||||||
{
|
{
|
||||||
struct allowedips_node *node = rcu_dereference_protected(trie,
|
struct allowedips_node *node = rcu_dereference_protected(trie, lockdep_is_held(lock));
|
||||||
lockdep_is_held(lock));
|
|
||||||
struct allowedips_node *parent = NULL;
|
struct allowedips_node *parent = NULL;
|
||||||
bool exact = false;
|
bool exact = false;
|
||||||
|
|
||||||
@ -202,13 +157,24 @@ static bool node_placement(struct allowedips_node __rcu *trie, const u8 *key,
|
|||||||
exact = true;
|
exact = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
node = rcu_dereference_protected(CHOOSE_NODE(parent, key),
|
node = rcu_dereference_protected(parent->bit[choose(parent, key)], lockdep_is_held(lock));
|
||||||
lockdep_is_held(lock));
|
|
||||||
}
|
}
|
||||||
*rnode = parent;
|
*rnode = parent;
|
||||||
return exact;
|
return exact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void connect_node(struct allowedips_node **parent, u8 bit, struct allowedips_node *node)
|
||||||
|
{
|
||||||
|
node->parent_bit_packed = (unsigned long)parent | bit;
|
||||||
|
rcu_assign_pointer(*parent, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void choose_and_connect_node(struct allowedips_node *parent, struct allowedips_node *node)
|
||||||
|
{
|
||||||
|
u8 bit = choose(parent, node->bits);
|
||||||
|
connect_node(&parent->bit[bit], bit, node);
|
||||||
|
}
|
||||||
|
|
||||||
static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key,
|
static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key,
|
||||||
u8 cidr, struct wg_peer *peer, struct mutex *lock)
|
u8 cidr, struct wg_peer *peer, struct mutex *lock)
|
||||||
{
|
{
|
||||||
@ -218,13 +184,13 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!rcu_access_pointer(*trie)) {
|
if (!rcu_access_pointer(*trie)) {
|
||||||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
node = kmem_cache_zalloc(node_cache, GFP_KERNEL);
|
||||||
if (unlikely(!node))
|
if (unlikely(!node))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
RCU_INIT_POINTER(node->peer, peer);
|
RCU_INIT_POINTER(node->peer, peer);
|
||||||
list_add_tail(&node->peer_list, &peer->allowedips_list);
|
list_add_tail(&node->peer_list, &peer->allowedips_list);
|
||||||
copy_and_assign_cidr(node, key, cidr, bits);
|
copy_and_assign_cidr(node, key, cidr, bits);
|
||||||
rcu_assign_pointer(*trie, node);
|
connect_node(trie, 2, node);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (node_placement(*trie, key, cidr, bits, &node, lock)) {
|
if (node_placement(*trie, key, cidr, bits, &node, lock)) {
|
||||||
@ -233,7 +199,7 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
newnode = kzalloc(sizeof(*newnode), GFP_KERNEL);
|
newnode = kmem_cache_zalloc(node_cache, GFP_KERNEL);
|
||||||
if (unlikely(!newnode))
|
if (unlikely(!newnode))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
RCU_INIT_POINTER(newnode->peer, peer);
|
RCU_INIT_POINTER(newnode->peer, peer);
|
||||||
@ -243,10 +209,10 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key,
|
|||||||
if (!node) {
|
if (!node) {
|
||||||
down = rcu_dereference_protected(*trie, lockdep_is_held(lock));
|
down = rcu_dereference_protected(*trie, lockdep_is_held(lock));
|
||||||
} else {
|
} else {
|
||||||
down = rcu_dereference_protected(CHOOSE_NODE(node, key),
|
const u8 bit = choose(node, key);
|
||||||
lockdep_is_held(lock));
|
down = rcu_dereference_protected(node->bit[bit], lockdep_is_held(lock));
|
||||||
if (!down) {
|
if (!down) {
|
||||||
rcu_assign_pointer(CHOOSE_NODE(node, key), newnode);
|
connect_node(&node->bit[bit], bit, newnode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,30 +220,29 @@ static int add(struct allowedips_node __rcu **trie, u8 bits, const u8 *key,
|
|||||||
parent = node;
|
parent = node;
|
||||||
|
|
||||||
if (newnode->cidr == cidr) {
|
if (newnode->cidr == cidr) {
|
||||||
rcu_assign_pointer(CHOOSE_NODE(newnode, down->bits), down);
|
choose_and_connect_node(newnode, down);
|
||||||
if (!parent)
|
if (!parent)
|
||||||
rcu_assign_pointer(*trie, newnode);
|
connect_node(trie, 2, newnode);
|
||||||
else
|
else
|
||||||
rcu_assign_pointer(CHOOSE_NODE(parent, newnode->bits),
|
choose_and_connect_node(parent, newnode);
|
||||||
newnode);
|
return 0;
|
||||||
} else {
|
|
||||||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
|
||||||
if (unlikely(!node)) {
|
|
||||||
list_del(&newnode->peer_list);
|
|
||||||
kfree(newnode);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
INIT_LIST_HEAD(&node->peer_list);
|
|
||||||
copy_and_assign_cidr(node, newnode->bits, cidr, bits);
|
|
||||||
|
|
||||||
rcu_assign_pointer(CHOOSE_NODE(node, down->bits), down);
|
|
||||||
rcu_assign_pointer(CHOOSE_NODE(node, newnode->bits), newnode);
|
|
||||||
if (!parent)
|
|
||||||
rcu_assign_pointer(*trie, node);
|
|
||||||
else
|
|
||||||
rcu_assign_pointer(CHOOSE_NODE(parent, node->bits),
|
|
||||||
node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node = kmem_cache_zalloc(node_cache, GFP_KERNEL);
|
||||||
|
if (unlikely(!node)) {
|
||||||
|
list_del(&newnode->peer_list);
|
||||||
|
kmem_cache_free(node_cache, newnode);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
INIT_LIST_HEAD(&node->peer_list);
|
||||||
|
copy_and_assign_cidr(node, newnode->bits, cidr, bits);
|
||||||
|
|
||||||
|
choose_and_connect_node(node, down);
|
||||||
|
choose_and_connect_node(node, newnode);
|
||||||
|
if (!parent)
|
||||||
|
connect_node(trie, 2, node);
|
||||||
|
else
|
||||||
|
choose_and_connect_node(parent, node);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,9 +300,41 @@ int wg_allowedips_insert_v6(struct allowedips *table, const struct in6_addr *ip,
|
|||||||
void wg_allowedips_remove_by_peer(struct allowedips *table,
|
void wg_allowedips_remove_by_peer(struct allowedips *table,
|
||||||
struct wg_peer *peer, struct mutex *lock)
|
struct wg_peer *peer, struct mutex *lock)
|
||||||
{
|
{
|
||||||
|
struct allowedips_node *node, *child, **parent_bit, *parent, *tmp;
|
||||||
|
bool free_parent;
|
||||||
|
|
||||||
|
if (list_empty(&peer->allowedips_list))
|
||||||
|
return;
|
||||||
++table->seq;
|
++table->seq;
|
||||||
walk_remove_by_peer(&table->root4, peer, lock);
|
list_for_each_entry_safe(node, tmp, &peer->allowedips_list, peer_list) {
|
||||||
walk_remove_by_peer(&table->root6, peer, lock);
|
list_del_init(&node->peer_list);
|
||||||
|
RCU_INIT_POINTER(node->peer, NULL);
|
||||||
|
if (node->bit[0] && node->bit[1])
|
||||||
|
continue;
|
||||||
|
child = rcu_dereference_protected(node->bit[!rcu_access_pointer(node->bit[0])],
|
||||||
|
lockdep_is_held(lock));
|
||||||
|
if (child)
|
||||||
|
child->parent_bit_packed = node->parent_bit_packed;
|
||||||
|
parent_bit = (struct allowedips_node **)(node->parent_bit_packed & ~3UL);
|
||||||
|
*parent_bit = child;
|
||||||
|
parent = (void *)parent_bit -
|
||||||
|
offsetof(struct allowedips_node, bit[node->parent_bit_packed & 1]);
|
||||||
|
free_parent = !rcu_access_pointer(node->bit[0]) &&
|
||||||
|
!rcu_access_pointer(node->bit[1]) &&
|
||||||
|
(node->parent_bit_packed & 3) <= 1 &&
|
||||||
|
!rcu_access_pointer(parent->peer);
|
||||||
|
if (free_parent)
|
||||||
|
child = rcu_dereference_protected(
|
||||||
|
parent->bit[!(node->parent_bit_packed & 1)],
|
||||||
|
lockdep_is_held(lock));
|
||||||
|
call_rcu(&node->rcu, node_free_rcu);
|
||||||
|
if (!free_parent)
|
||||||
|
continue;
|
||||||
|
if (child)
|
||||||
|
child->parent_bit_packed = parent->parent_bit_packed;
|
||||||
|
*(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child;
|
||||||
|
call_rcu(&parent->rcu, node_free_rcu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int wg_allowedips_read_node(struct allowedips_node *node, u8 ip[16], u8 *cidr)
|
int wg_allowedips_read_node(struct allowedips_node *node, u8 ip[16], u8 *cidr)
|
||||||
@ -374,4 +371,16 @@ struct wg_peer *wg_allowedips_lookup_src(struct allowedips *table,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __init wg_allowedips_slab_init(void)
|
||||||
|
{
|
||||||
|
node_cache = KMEM_CACHE(allowedips_node, 0);
|
||||||
|
return node_cache ? 0 : -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wg_allowedips_slab_uninit(void)
|
||||||
|
{
|
||||||
|
rcu_barrier();
|
||||||
|
kmem_cache_destroy(node_cache);
|
||||||
|
}
|
||||||
|
|
||||||
#include "selftest/allowedips.c"
|
#include "selftest/allowedips.c"
|
||||||
|
@ -15,14 +15,11 @@ struct wg_peer;
|
|||||||
struct allowedips_node {
|
struct allowedips_node {
|
||||||
struct wg_peer __rcu *peer;
|
struct wg_peer __rcu *peer;
|
||||||
struct allowedips_node __rcu *bit[2];
|
struct allowedips_node __rcu *bit[2];
|
||||||
/* While it may seem scandalous that we waste space for v4,
|
|
||||||
* we're alloc'ing to the nearest power of 2 anyway, so this
|
|
||||||
* doesn't actually make a difference.
|
|
||||||
*/
|
|
||||||
u8 bits[16] __aligned(__alignof(u64));
|
|
||||||
u8 cidr, bit_at_a, bit_at_b, bitlen;
|
u8 cidr, bit_at_a, bit_at_b, bitlen;
|
||||||
|
u8 bits[16] __aligned(__alignof(u64));
|
||||||
|
|
||||||
/* Keep rarely used list at bottom to be beyond cache line. */
|
/* Keep rarely used members at bottom to be beyond cache line. */
|
||||||
|
unsigned long parent_bit_packed;
|
||||||
union {
|
union {
|
||||||
struct list_head peer_list;
|
struct list_head peer_list;
|
||||||
struct rcu_head rcu;
|
struct rcu_head rcu;
|
||||||
@ -33,7 +30,7 @@ struct allowedips {
|
|||||||
struct allowedips_node __rcu *root4;
|
struct allowedips_node __rcu *root4;
|
||||||
struct allowedips_node __rcu *root6;
|
struct allowedips_node __rcu *root6;
|
||||||
u64 seq;
|
u64 seq;
|
||||||
};
|
} __aligned(4); /* We pack the lower 2 bits of &root, but m68k only gives 16-bit alignment. */
|
||||||
|
|
||||||
void wg_allowedips_init(struct allowedips *table);
|
void wg_allowedips_init(struct allowedips *table);
|
||||||
void wg_allowedips_free(struct allowedips *table, struct mutex *mutex);
|
void wg_allowedips_free(struct allowedips *table, struct mutex *mutex);
|
||||||
@ -56,4 +53,7 @@ struct wg_peer *wg_allowedips_lookup_src(struct allowedips *table,
|
|||||||
bool wg_allowedips_selftest(void);
|
bool wg_allowedips_selftest(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int wg_allowedips_slab_init(void);
|
||||||
|
void wg_allowedips_slab_uninit(void);
|
||||||
|
|
||||||
#endif /* _WG_ALLOWEDIPS_H */
|
#endif /* _WG_ALLOWEDIPS_H */
|
||||||
|
@ -21,13 +21,22 @@ static int __init mod_init(void)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ret = wg_allowedips_slab_init();
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_allowedips;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
ret = -ENOTRECOVERABLE;
|
||||||
if (!wg_allowedips_selftest() || !wg_packet_counter_selftest() ||
|
if (!wg_allowedips_selftest() || !wg_packet_counter_selftest() ||
|
||||||
!wg_ratelimiter_selftest())
|
!wg_ratelimiter_selftest())
|
||||||
return -ENOTRECOVERABLE;
|
goto err_peer;
|
||||||
#endif
|
#endif
|
||||||
wg_noise_init();
|
wg_noise_init();
|
||||||
|
|
||||||
|
ret = wg_peer_init();
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_peer;
|
||||||
|
|
||||||
ret = wg_device_init();
|
ret = wg_device_init();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_device;
|
goto err_device;
|
||||||
@ -44,6 +53,10 @@ static int __init mod_init(void)
|
|||||||
err_netlink:
|
err_netlink:
|
||||||
wg_device_uninit();
|
wg_device_uninit();
|
||||||
err_device:
|
err_device:
|
||||||
|
wg_peer_uninit();
|
||||||
|
err_peer:
|
||||||
|
wg_allowedips_slab_uninit();
|
||||||
|
err_allowedips:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +64,8 @@ static void __exit mod_exit(void)
|
|||||||
{
|
{
|
||||||
wg_genetlink_uninit();
|
wg_genetlink_uninit();
|
||||||
wg_device_uninit();
|
wg_device_uninit();
|
||||||
|
wg_peer_uninit();
|
||||||
|
wg_allowedips_slab_uninit();
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(mod_init);
|
module_init(mod_init);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <linux/rcupdate.h>
|
#include <linux/rcupdate.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
|
||||||
|
static struct kmem_cache *peer_cache;
|
||||||
static atomic64_t peer_counter = ATOMIC64_INIT(0);
|
static atomic64_t peer_counter = ATOMIC64_INIT(0);
|
||||||
|
|
||||||
struct wg_peer *wg_peer_create(struct wg_device *wg,
|
struct wg_peer *wg_peer_create(struct wg_device *wg,
|
||||||
@ -29,10 +30,10 @@ struct wg_peer *wg_peer_create(struct wg_device *wg,
|
|||||||
if (wg->num_peers >= MAX_PEERS_PER_DEVICE)
|
if (wg->num_peers >= MAX_PEERS_PER_DEVICE)
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
peer = kzalloc(sizeof(*peer), GFP_KERNEL);
|
peer = kmem_cache_zalloc(peer_cache, GFP_KERNEL);
|
||||||
if (unlikely(!peer))
|
if (unlikely(!peer))
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL))
|
if (unlikely(dst_cache_init(&peer->endpoint_cache, GFP_KERNEL)))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
peer->device = wg;
|
peer->device = wg;
|
||||||
@ -64,7 +65,7 @@ struct wg_peer *wg_peer_create(struct wg_device *wg,
|
|||||||
return peer;
|
return peer;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
kfree(peer);
|
kmem_cache_free(peer_cache, peer);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,7 @@ static void peer_make_dead(struct wg_peer *peer)
|
|||||||
/* Mark as dead, so that we don't allow jumping contexts after. */
|
/* Mark as dead, so that we don't allow jumping contexts after. */
|
||||||
WRITE_ONCE(peer->is_dead, true);
|
WRITE_ONCE(peer->is_dead, true);
|
||||||
|
|
||||||
/* The caller must now synchronize_rcu() for this to take effect. */
|
/* The caller must now synchronize_net() for this to take effect. */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void peer_remove_after_dead(struct wg_peer *peer)
|
static void peer_remove_after_dead(struct wg_peer *peer)
|
||||||
@ -160,7 +161,7 @@ void wg_peer_remove(struct wg_peer *peer)
|
|||||||
lockdep_assert_held(&peer->device->device_update_lock);
|
lockdep_assert_held(&peer->device->device_update_lock);
|
||||||
|
|
||||||
peer_make_dead(peer);
|
peer_make_dead(peer);
|
||||||
synchronize_rcu();
|
synchronize_net();
|
||||||
peer_remove_after_dead(peer);
|
peer_remove_after_dead(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +179,7 @@ void wg_peer_remove_all(struct wg_device *wg)
|
|||||||
peer_make_dead(peer);
|
peer_make_dead(peer);
|
||||||
list_add_tail(&peer->peer_list, &dead_peers);
|
list_add_tail(&peer->peer_list, &dead_peers);
|
||||||
}
|
}
|
||||||
synchronize_rcu();
|
synchronize_net();
|
||||||
list_for_each_entry_safe(peer, temp, &dead_peers, peer_list)
|
list_for_each_entry_safe(peer, temp, &dead_peers, peer_list)
|
||||||
peer_remove_after_dead(peer);
|
peer_remove_after_dead(peer);
|
||||||
}
|
}
|
||||||
@ -193,7 +194,8 @@ static void rcu_release(struct rcu_head *rcu)
|
|||||||
/* The final zeroing takes care of clearing any remaining handshake key
|
/* The final zeroing takes care of clearing any remaining handshake key
|
||||||
* material and other potentially sensitive information.
|
* material and other potentially sensitive information.
|
||||||
*/
|
*/
|
||||||
kfree_sensitive(peer);
|
memzero_explicit(peer, sizeof(*peer));
|
||||||
|
kmem_cache_free(peer_cache, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kref_release(struct kref *refcount)
|
static void kref_release(struct kref *refcount)
|
||||||
@ -225,3 +227,14 @@ void wg_peer_put(struct wg_peer *peer)
|
|||||||
return;
|
return;
|
||||||
kref_put(&peer->refcount, kref_release);
|
kref_put(&peer->refcount, kref_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __init wg_peer_init(void)
|
||||||
|
{
|
||||||
|
peer_cache = KMEM_CACHE(wg_peer, 0);
|
||||||
|
return peer_cache ? 0 : -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wg_peer_uninit(void)
|
||||||
|
{
|
||||||
|
kmem_cache_destroy(peer_cache);
|
||||||
|
}
|
||||||
|
@ -80,4 +80,7 @@ void wg_peer_put(struct wg_peer *peer);
|
|||||||
void wg_peer_remove(struct wg_peer *peer);
|
void wg_peer_remove(struct wg_peer *peer);
|
||||||
void wg_peer_remove_all(struct wg_device *wg);
|
void wg_peer_remove_all(struct wg_device *wg);
|
||||||
|
|
||||||
|
int wg_peer_init(void);
|
||||||
|
void wg_peer_uninit(void);
|
||||||
|
|
||||||
#endif /* _WG_PEER_H */
|
#endif /* _WG_PEER_H */
|
||||||
|
@ -19,32 +19,22 @@
|
|||||||
|
|
||||||
#include <linux/siphash.h>
|
#include <linux/siphash.h>
|
||||||
|
|
||||||
static __init void swap_endian_and_apply_cidr(u8 *dst, const u8 *src, u8 bits,
|
|
||||||
u8 cidr)
|
|
||||||
{
|
|
||||||
swap_endian(dst, src, bits);
|
|
||||||
memset(dst + (cidr + 7) / 8, 0, bits / 8 - (cidr + 7) / 8);
|
|
||||||
if (cidr)
|
|
||||||
dst[(cidr + 7) / 8 - 1] &= ~0U << ((8 - (cidr % 8)) % 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __init void print_node(struct allowedips_node *node, u8 bits)
|
static __init void print_node(struct allowedips_node *node, u8 bits)
|
||||||
{
|
{
|
||||||
char *fmt_connection = KERN_DEBUG "\t\"%p/%d\" -> \"%p/%d\";\n";
|
char *fmt_connection = KERN_DEBUG "\t\"%p/%d\" -> \"%p/%d\";\n";
|
||||||
char *fmt_declaration = KERN_DEBUG
|
char *fmt_declaration = KERN_DEBUG "\t\"%p/%d\"[style=%s, color=\"#%06x\"];\n";
|
||||||
"\t\"%p/%d\"[style=%s, color=\"#%06x\"];\n";
|
u8 ip1[16], ip2[16], cidr1, cidr2;
|
||||||
char *style = "dotted";
|
char *style = "dotted";
|
||||||
u8 ip1[16], ip2[16];
|
|
||||||
u32 color = 0;
|
u32 color = 0;
|
||||||
|
|
||||||
|
if (node == NULL)
|
||||||
|
return;
|
||||||
if (bits == 32) {
|
if (bits == 32) {
|
||||||
fmt_connection = KERN_DEBUG "\t\"%pI4/%d\" -> \"%pI4/%d\";\n";
|
fmt_connection = KERN_DEBUG "\t\"%pI4/%d\" -> \"%pI4/%d\";\n";
|
||||||
fmt_declaration = KERN_DEBUG
|
fmt_declaration = KERN_DEBUG "\t\"%pI4/%d\"[style=%s, color=\"#%06x\"];\n";
|
||||||
"\t\"%pI4/%d\"[style=%s, color=\"#%06x\"];\n";
|
|
||||||
} else if (bits == 128) {
|
} else if (bits == 128) {
|
||||||
fmt_connection = KERN_DEBUG "\t\"%pI6/%d\" -> \"%pI6/%d\";\n";
|
fmt_connection = KERN_DEBUG "\t\"%pI6/%d\" -> \"%pI6/%d\";\n";
|
||||||
fmt_declaration = KERN_DEBUG
|
fmt_declaration = KERN_DEBUG "\t\"%pI6/%d\"[style=%s, color=\"#%06x\"];\n";
|
||||||
"\t\"%pI6/%d\"[style=%s, color=\"#%06x\"];\n";
|
|
||||||
}
|
}
|
||||||
if (node->peer) {
|
if (node->peer) {
|
||||||
hsiphash_key_t key = { { 0 } };
|
hsiphash_key_t key = { { 0 } };
|
||||||
@ -55,24 +45,20 @@ static __init void print_node(struct allowedips_node *node, u8 bits)
|
|||||||
hsiphash_1u32(0xabad1dea, &key) % 200;
|
hsiphash_1u32(0xabad1dea, &key) % 200;
|
||||||
style = "bold";
|
style = "bold";
|
||||||
}
|
}
|
||||||
swap_endian_and_apply_cidr(ip1, node->bits, bits, node->cidr);
|
wg_allowedips_read_node(node, ip1, &cidr1);
|
||||||
printk(fmt_declaration, ip1, node->cidr, style, color);
|
printk(fmt_declaration, ip1, cidr1, style, color);
|
||||||
if (node->bit[0]) {
|
if (node->bit[0]) {
|
||||||
swap_endian_and_apply_cidr(ip2,
|
wg_allowedips_read_node(rcu_dereference_raw(node->bit[0]), ip2, &cidr2);
|
||||||
rcu_dereference_raw(node->bit[0])->bits, bits,
|
printk(fmt_connection, ip1, cidr1, ip2, cidr2);
|
||||||
node->cidr);
|
|
||||||
printk(fmt_connection, ip1, node->cidr, ip2,
|
|
||||||
rcu_dereference_raw(node->bit[0])->cidr);
|
|
||||||
print_node(rcu_dereference_raw(node->bit[0]), bits);
|
|
||||||
}
|
}
|
||||||
if (node->bit[1]) {
|
if (node->bit[1]) {
|
||||||
swap_endian_and_apply_cidr(ip2,
|
wg_allowedips_read_node(rcu_dereference_raw(node->bit[1]), ip2, &cidr2);
|
||||||
rcu_dereference_raw(node->bit[1])->bits,
|
printk(fmt_connection, ip1, cidr1, ip2, cidr2);
|
||||||
bits, node->cidr);
|
|
||||||
printk(fmt_connection, ip1, node->cidr, ip2,
|
|
||||||
rcu_dereference_raw(node->bit[1])->cidr);
|
|
||||||
print_node(rcu_dereference_raw(node->bit[1]), bits);
|
|
||||||
}
|
}
|
||||||
|
if (node->bit[0])
|
||||||
|
print_node(rcu_dereference_raw(node->bit[0]), bits);
|
||||||
|
if (node->bit[1])
|
||||||
|
print_node(rcu_dereference_raw(node->bit[1]), bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init void print_tree(struct allowedips_node __rcu *top, u8 bits)
|
static __init void print_tree(struct allowedips_node __rcu *top, u8 bits)
|
||||||
@ -121,8 +107,8 @@ static __init inline union nf_inet_addr horrible_cidr_to_mask(u8 cidr)
|
|||||||
{
|
{
|
||||||
union nf_inet_addr mask;
|
union nf_inet_addr mask;
|
||||||
|
|
||||||
memset(&mask, 0x00, 128 / 8);
|
memset(&mask, 0, sizeof(mask));
|
||||||
memset(&mask, 0xff, cidr / 8);
|
memset(&mask.all, 0xff, cidr / 8);
|
||||||
if (cidr % 32)
|
if (cidr % 32)
|
||||||
mask.all[cidr / 32] = (__force u32)htonl(
|
mask.all[cidr / 32] = (__force u32)htonl(
|
||||||
(0xFFFFFFFFUL << (32 - (cidr % 32))) & 0xFFFFFFFFUL);
|
(0xFFFFFFFFUL << (32 - (cidr % 32))) & 0xFFFFFFFFUL);
|
||||||
@ -149,42 +135,36 @@ horrible_mask_self(struct horrible_allowedips_node *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static __init inline bool
|
static __init inline bool
|
||||||
horrible_match_v4(const struct horrible_allowedips_node *node,
|
horrible_match_v4(const struct horrible_allowedips_node *node, struct in_addr *ip)
|
||||||
struct in_addr *ip)
|
|
||||||
{
|
{
|
||||||
return (ip->s_addr & node->mask.ip) == node->ip.ip;
|
return (ip->s_addr & node->mask.ip) == node->ip.ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init inline bool
|
static __init inline bool
|
||||||
horrible_match_v6(const struct horrible_allowedips_node *node,
|
horrible_match_v6(const struct horrible_allowedips_node *node, struct in6_addr *ip)
|
||||||
struct in6_addr *ip)
|
|
||||||
{
|
{
|
||||||
return (ip->in6_u.u6_addr32[0] & node->mask.ip6[0]) ==
|
return (ip->in6_u.u6_addr32[0] & node->mask.ip6[0]) == node->ip.ip6[0] &&
|
||||||
node->ip.ip6[0] &&
|
(ip->in6_u.u6_addr32[1] & node->mask.ip6[1]) == node->ip.ip6[1] &&
|
||||||
(ip->in6_u.u6_addr32[1] & node->mask.ip6[1]) ==
|
(ip->in6_u.u6_addr32[2] & node->mask.ip6[2]) == node->ip.ip6[2] &&
|
||||||
node->ip.ip6[1] &&
|
|
||||||
(ip->in6_u.u6_addr32[2] & node->mask.ip6[2]) ==
|
|
||||||
node->ip.ip6[2] &&
|
|
||||||
(ip->in6_u.u6_addr32[3] & node->mask.ip6[3]) == node->ip.ip6[3];
|
(ip->in6_u.u6_addr32[3] & node->mask.ip6[3]) == node->ip.ip6[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init void
|
static __init void
|
||||||
horrible_insert_ordered(struct horrible_allowedips *table,
|
horrible_insert_ordered(struct horrible_allowedips *table, struct horrible_allowedips_node *node)
|
||||||
struct horrible_allowedips_node *node)
|
|
||||||
{
|
{
|
||||||
struct horrible_allowedips_node *other = NULL, *where = NULL;
|
struct horrible_allowedips_node *other = NULL, *where = NULL;
|
||||||
u8 my_cidr = horrible_mask_to_cidr(node->mask);
|
u8 my_cidr = horrible_mask_to_cidr(node->mask);
|
||||||
|
|
||||||
hlist_for_each_entry(other, &table->head, table) {
|
hlist_for_each_entry(other, &table->head, table) {
|
||||||
if (!memcmp(&other->mask, &node->mask,
|
if (other->ip_version == node->ip_version &&
|
||||||
sizeof(union nf_inet_addr)) &&
|
!memcmp(&other->mask, &node->mask, sizeof(union nf_inet_addr)) &&
|
||||||
!memcmp(&other->ip, &node->ip,
|
!memcmp(&other->ip, &node->ip, sizeof(union nf_inet_addr))) {
|
||||||
sizeof(union nf_inet_addr)) &&
|
|
||||||
other->ip_version == node->ip_version) {
|
|
||||||
other->value = node->value;
|
other->value = node->value;
|
||||||
kfree(node);
|
kfree(node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
hlist_for_each_entry(other, &table->head, table) {
|
||||||
where = other;
|
where = other;
|
||||||
if (horrible_mask_to_cidr(other->mask) <= my_cidr)
|
if (horrible_mask_to_cidr(other->mask) <= my_cidr)
|
||||||
break;
|
break;
|
||||||
@ -201,8 +181,7 @@ static __init int
|
|||||||
horrible_allowedips_insert_v4(struct horrible_allowedips *table,
|
horrible_allowedips_insert_v4(struct horrible_allowedips *table,
|
||||||
struct in_addr *ip, u8 cidr, void *value)
|
struct in_addr *ip, u8 cidr, void *value)
|
||||||
{
|
{
|
||||||
struct horrible_allowedips_node *node = kzalloc(sizeof(*node),
|
struct horrible_allowedips_node *node = kzalloc(sizeof(*node), GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
|
||||||
|
|
||||||
if (unlikely(!node))
|
if (unlikely(!node))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -219,8 +198,7 @@ static __init int
|
|||||||
horrible_allowedips_insert_v6(struct horrible_allowedips *table,
|
horrible_allowedips_insert_v6(struct horrible_allowedips *table,
|
||||||
struct in6_addr *ip, u8 cidr, void *value)
|
struct in6_addr *ip, u8 cidr, void *value)
|
||||||
{
|
{
|
||||||
struct horrible_allowedips_node *node = kzalloc(sizeof(*node),
|
struct horrible_allowedips_node *node = kzalloc(sizeof(*node), GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
|
||||||
|
|
||||||
if (unlikely(!node))
|
if (unlikely(!node))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -234,39 +212,43 @@ horrible_allowedips_insert_v6(struct horrible_allowedips *table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static __init void *
|
static __init void *
|
||||||
horrible_allowedips_lookup_v4(struct horrible_allowedips *table,
|
horrible_allowedips_lookup_v4(struct horrible_allowedips *table, struct in_addr *ip)
|
||||||
struct in_addr *ip)
|
|
||||||
{
|
{
|
||||||
struct horrible_allowedips_node *node;
|
struct horrible_allowedips_node *node;
|
||||||
void *ret = NULL;
|
|
||||||
|
|
||||||
hlist_for_each_entry(node, &table->head, table) {
|
hlist_for_each_entry(node, &table->head, table) {
|
||||||
if (node->ip_version != 4)
|
if (node->ip_version == 4 && horrible_match_v4(node, ip))
|
||||||
continue;
|
return node->value;
|
||||||
if (horrible_match_v4(node, ip)) {
|
|
||||||
ret = node->value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init void *
|
static __init void *
|
||||||
horrible_allowedips_lookup_v6(struct horrible_allowedips *table,
|
horrible_allowedips_lookup_v6(struct horrible_allowedips *table, struct in6_addr *ip)
|
||||||
struct in6_addr *ip)
|
|
||||||
{
|
{
|
||||||
struct horrible_allowedips_node *node;
|
struct horrible_allowedips_node *node;
|
||||||
void *ret = NULL;
|
|
||||||
|
|
||||||
hlist_for_each_entry(node, &table->head, table) {
|
hlist_for_each_entry(node, &table->head, table) {
|
||||||
if (node->ip_version != 6)
|
if (node->ip_version == 6 && horrible_match_v6(node, ip))
|
||||||
continue;
|
return node->value;
|
||||||
if (horrible_match_v6(node, ip)) {
|
|
||||||
ret = node->value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static __init void
|
||||||
|
horrible_allowedips_remove_by_value(struct horrible_allowedips *table, void *value)
|
||||||
|
{
|
||||||
|
struct horrible_allowedips_node *node;
|
||||||
|
struct hlist_node *h;
|
||||||
|
|
||||||
|
hlist_for_each_entry_safe(node, h, &table->head, table) {
|
||||||
|
if (node->value != value)
|
||||||
|
continue;
|
||||||
|
hlist_del(&node->table);
|
||||||
|
kfree(node);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init bool randomized_test(void)
|
static __init bool randomized_test(void)
|
||||||
@ -296,6 +278,7 @@ static __init bool randomized_test(void)
|
|||||||
goto free;
|
goto free;
|
||||||
}
|
}
|
||||||
kref_init(&peers[i]->refcount);
|
kref_init(&peers[i]->refcount);
|
||||||
|
INIT_LIST_HEAD(&peers[i]->allowedips_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&mutex);
|
mutex_lock(&mutex);
|
||||||
@ -333,7 +316,7 @@ static __init bool randomized_test(void)
|
|||||||
if (wg_allowedips_insert_v4(&t,
|
if (wg_allowedips_insert_v4(&t,
|
||||||
(struct in_addr *)mutated,
|
(struct in_addr *)mutated,
|
||||||
cidr, peer, &mutex) < 0) {
|
cidr, peer, &mutex) < 0) {
|
||||||
pr_err("allowedips random malloc: FAIL\n");
|
pr_err("allowedips random self-test malloc: FAIL\n");
|
||||||
goto free_locked;
|
goto free_locked;
|
||||||
}
|
}
|
||||||
if (horrible_allowedips_insert_v4(&h,
|
if (horrible_allowedips_insert_v4(&h,
|
||||||
@ -396,23 +379,33 @@ static __init bool randomized_test(void)
|
|||||||
print_tree(t.root6, 128);
|
print_tree(t.root6, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NUM_QUERIES; ++i) {
|
for (j = 0;; ++j) {
|
||||||
prandom_bytes(ip, 4);
|
for (i = 0; i < NUM_QUERIES; ++i) {
|
||||||
if (lookup(t.root4, 32, ip) !=
|
prandom_bytes(ip, 4);
|
||||||
horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip)) {
|
if (lookup(t.root4, 32, ip) != horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip)) {
|
||||||
pr_err("allowedips random self-test: FAIL\n");
|
horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip);
|
||||||
goto free;
|
pr_err("allowedips random v4 self-test: FAIL\n");
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
|
prandom_bytes(ip, 16);
|
||||||
|
if (lookup(t.root6, 128, ip) != horrible_allowedips_lookup_v6(&h, (struct in6_addr *)ip)) {
|
||||||
|
pr_err("allowedips random v6 self-test: FAIL\n");
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (j >= NUM_PEERS)
|
||||||
|
break;
|
||||||
|
mutex_lock(&mutex);
|
||||||
|
wg_allowedips_remove_by_peer(&t, peers[j], &mutex);
|
||||||
|
mutex_unlock(&mutex);
|
||||||
|
horrible_allowedips_remove_by_value(&h, peers[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NUM_QUERIES; ++i) {
|
if (t.root4 || t.root6) {
|
||||||
prandom_bytes(ip, 16);
|
pr_err("allowedips random self-test removal: FAIL\n");
|
||||||
if (lookup(t.root6, 128, ip) !=
|
goto free;
|
||||||
horrible_allowedips_lookup_v6(&h, (struct in6_addr *)ip)) {
|
|
||||||
pr_err("allowedips random self-test: FAIL\n");
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
free:
|
free:
|
||||||
|
@ -87,7 +87,7 @@ static const struct ieee80211_ops mt76x0e_ops = {
|
|||||||
.reconfig_complete = mt76x02_reconfig_complete,
|
.reconfig_complete = mt76x02_reconfig_complete,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mt76x0e_register_device(struct mt76x02_dev *dev)
|
static int mt76x0e_init_hardware(struct mt76x02_dev *dev, bool resume)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -100,9 +100,11 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = mt76x02_dma_init(dev);
|
if (!resume) {
|
||||||
if (err < 0)
|
err = mt76x02_dma_init(dev);
|
||||||
return err;
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = mt76x0_init_hardware(dev);
|
err = mt76x0_init_hardware(dev);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -123,6 +125,17 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev)
|
|||||||
mt76_clear(dev, 0x110, BIT(9));
|
mt76_clear(dev, 0x110, BIT(9));
|
||||||
mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
|
mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mt76x0e_register_device(struct mt76x02_dev *dev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = mt76x0e_init_hardware(dev, false);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
err = mt76x0_register_device(dev);
|
err = mt76x0_register_device(dev);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -167,6 +180,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
mt76_pci_disable_aspm(pdev);
|
||||||
|
|
||||||
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops,
|
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops,
|
||||||
&drv_ops);
|
&drv_ops);
|
||||||
if (!mdev)
|
if (!mdev)
|
||||||
@ -220,6 +235,60 @@ mt76x0e_remove(struct pci_dev *pdev)
|
|||||||
mt76_free_device(mdev);
|
mt76_free_device(mdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int mt76x0e_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
|
{
|
||||||
|
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||||
|
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
mt76_worker_disable(&mdev->tx_worker);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mdev->phy.q_tx); i++)
|
||||||
|
mt76_queue_tx_cleanup(dev, mdev->phy.q_tx[i], true);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mdev->q_mcu); i++)
|
||||||
|
mt76_queue_tx_cleanup(dev, mdev->q_mcu[i], true);
|
||||||
|
napi_disable(&mdev->tx_napi);
|
||||||
|
|
||||||
|
mt76_for_each_q_rx(mdev, i)
|
||||||
|
napi_disable(&mdev->napi[i]);
|
||||||
|
|
||||||
|
mt76x02_dma_disable(dev);
|
||||||
|
mt76x02_mcu_cleanup(dev);
|
||||||
|
mt76x0_chip_onoff(dev, false, false);
|
||||||
|
|
||||||
|
pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
|
||||||
|
pci_save_state(pdev);
|
||||||
|
|
||||||
|
return pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mt76x0e_resume(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||||
|
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
err = pci_set_power_state(pdev, PCI_D0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
pci_restore_state(pdev);
|
||||||
|
|
||||||
|
mt76_worker_enable(&mdev->tx_worker);
|
||||||
|
|
||||||
|
mt76_for_each_q_rx(mdev, i) {
|
||||||
|
mt76_queue_rx_reset(dev, i);
|
||||||
|
napi_enable(&mdev->napi[i]);
|
||||||
|
napi_schedule(&mdev->napi[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
napi_enable(&mdev->tx_napi);
|
||||||
|
napi_schedule(&mdev->tx_napi);
|
||||||
|
|
||||||
|
return mt76x0e_init_hardware(dev, true);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
static const struct pci_device_id mt76x0e_device_table[] = {
|
static const struct pci_device_id mt76x0e_device_table[] = {
|
||||||
{ PCI_DEVICE(0x14c3, 0x7610) },
|
{ PCI_DEVICE(0x14c3, 0x7610) },
|
||||||
{ PCI_DEVICE(0x14c3, 0x7630) },
|
{ PCI_DEVICE(0x14c3, 0x7630) },
|
||||||
@ -237,6 +306,10 @@ static struct pci_driver mt76x0e_driver = {
|
|||||||
.id_table = mt76x0e_device_table,
|
.id_table = mt76x0e_device_table,
|
||||||
.probe = mt76x0e_probe,
|
.probe = mt76x0e_probe,
|
||||||
.remove = mt76x0e_remove,
|
.remove = mt76x0e_remove,
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.suspend = mt76x0e_suspend,
|
||||||
|
.resume = mt76x0e_resume,
|
||||||
|
#endif /* CONFIG_PM */
|
||||||
};
|
};
|
||||||
|
|
||||||
module_pci_driver(mt76x0e_driver);
|
module_pci_driver(mt76x0e_driver);
|
||||||
|
@ -391,29 +391,37 @@ static void
|
|||||||
mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
|
mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
|
||||||
u16 wlan_idx)
|
u16 wlan_idx)
|
||||||
{
|
{
|
||||||
struct mt7921_mcu_wlan_info_event *wtbl_info =
|
struct mt7921_mcu_wlan_info_event *wtbl_info;
|
||||||
(struct mt7921_mcu_wlan_info_event *)(skb->data);
|
|
||||||
struct rate_info rate = {};
|
|
||||||
u8 curr_idx = wtbl_info->rate_info.rate_idx;
|
|
||||||
u16 curr = le16_to_cpu(wtbl_info->rate_info.rate[curr_idx]);
|
|
||||||
struct mt7921_mcu_peer_cap peer = wtbl_info->peer_cap;
|
|
||||||
struct mt76_phy *mphy = &dev->mphy;
|
struct mt76_phy *mphy = &dev->mphy;
|
||||||
struct mt7921_sta_stats *stats;
|
struct mt7921_sta_stats *stats;
|
||||||
|
struct rate_info rate = {};
|
||||||
struct mt7921_sta *msta;
|
struct mt7921_sta *msta;
|
||||||
struct mt76_wcid *wcid;
|
struct mt76_wcid *wcid;
|
||||||
|
u8 idx;
|
||||||
|
|
||||||
if (wlan_idx >= MT76_N_WCIDS)
|
if (wlan_idx >= MT76_N_WCIDS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
wtbl_info = (struct mt7921_mcu_wlan_info_event *)skb->data;
|
||||||
|
idx = wtbl_info->rate_info.rate_idx;
|
||||||
|
if (idx >= ARRAY_SIZE(wtbl_info->rate_info.rate))
|
||||||
|
return;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
|
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
|
||||||
if (!wcid)
|
if (!wcid)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
msta = container_of(wcid, struct mt7921_sta, wcid);
|
msta = container_of(wcid, struct mt7921_sta, wcid);
|
||||||
stats = &msta->stats;
|
stats = &msta->stats;
|
||||||
|
|
||||||
/* current rate */
|
/* current rate */
|
||||||
mt7921_mcu_tx_rate_parse(mphy, &peer, &rate, curr);
|
mt7921_mcu_tx_rate_parse(mphy, &wtbl_info->peer_cap, &rate,
|
||||||
|
le16_to_cpu(wtbl_info->rate_info.rate[idx]));
|
||||||
stats->tx_rate = rate;
|
stats->tx_rate = rate;
|
||||||
|
out:
|
||||||
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -684,6 +684,7 @@ static void xenvif_disconnect_queue(struct xenvif_queue *queue)
|
|||||||
{
|
{
|
||||||
if (queue->task) {
|
if (queue->task) {
|
||||||
kthread_stop(queue->task);
|
kthread_stop(queue->task);
|
||||||
|
put_task_struct(queue->task);
|
||||||
queue->task = NULL;
|
queue->task = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,6 +746,11 @@ int xenvif_connect_data(struct xenvif_queue *queue,
|
|||||||
if (IS_ERR(task))
|
if (IS_ERR(task))
|
||||||
goto kthread_err;
|
goto kthread_err;
|
||||||
queue->task = task;
|
queue->task = task;
|
||||||
|
/*
|
||||||
|
* Take a reference to the task in order to prevent it from being freed
|
||||||
|
* if the thread function returns before kthread_stop is called.
|
||||||
|
*/
|
||||||
|
get_task_struct(task);
|
||||||
|
|
||||||
task = kthread_run(xenvif_dealloc_kthread, queue,
|
task = kthread_run(xenvif_dealloc_kthread, queue,
|
||||||
"%s-dealloc", queue->name);
|
"%s-dealloc", queue->name);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user