Merge branch 'acpi-scan' into acpi-pm
Conflicts:
drivers/acpi/scan.c
The conflict is resolved by moving the just introduced
acpi_device_is_first_physical_node() to bus.c and using
the existing acpi_companion_match() from there.
There will be an additional commit to combine the two.
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index e63b446..13f888a 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -952,6 +952,14 @@
$(KBUILD_ARFLAGS) set by the top level Makefile to "D" (deterministic
mode) if this option is supported by $(AR).
+ ARCH_CPPFLAGS, ARCH_AFLAGS, ARCH_CFLAGS Overrides the kbuild defaults
+
+ These variables are appended to the KBUILD_CPPFLAGS,
+ KBUILD_AFLAGS, and KBUILD_CFLAGS, respectively, after the
+ top-level Makefile has set any other flags. This provides a
+ means for an architecture to override the defaults.
+
+
--- 6.2 Add prerequisites to archheaders:
The archheaders: rule is used to generate header files that
diff --git a/MAINTAINERS b/MAINTAINERS
index fd60784..2d3d55c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7019,6 +7019,7 @@
F: net/*/netfilter.c
F: net/*/netfilter/
F: net/netfilter/
+F: net/bridge/br_netfilter*.c
NETLABEL
M: Paul Moore <paul@paul-moore.com>
diff --git a/Makefile b/Makefile
index 257ef58..2f49d89 100644
--- a/Makefile
+++ b/Makefile
@@ -780,10 +780,11 @@
include scripts/Makefile.kasan
include scripts/Makefile.extrawarn
-# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
-KBUILD_CPPFLAGS += $(KCPPFLAGS)
-KBUILD_AFLAGS += $(KAFLAGS)
-KBUILD_CFLAGS += $(KCFLAGS)
+# Add any arch overrides and user supplied CPPFLAGS, AFLAGS and CFLAGS as the
+# last assignments
+KBUILD_CPPFLAGS += $(ARCH_CPPFLAGS) $(KCPPFLAGS)
+KBUILD_AFLAGS += $(ARCH_AFLAGS) $(KAFLAGS)
+KBUILD_CFLAGS += $(ARCH_CFLAGS) $(KCFLAGS)
# Use --build-id when available.
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index e7cee0a..91cf405 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -115,6 +115,7 @@
config ARC_CPU_750D
bool "ARC750D"
+ select ARC_CANT_LLSC
help
Support for ARC750 core
@@ -362,7 +363,7 @@
config ARC_HAS_LLSC
bool "Insn: LLOCK/SCOND (efficient atomic ops)"
default y
- depends on !ARC_CPU_750D && !ARC_CANT_LLSC
+ depends on !ARC_CANT_LLSC
config ARC_HAS_SWAPE
bool "Insn: SWAPE (endian-swap)"
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 6107062..46d8731 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -49,7 +49,8 @@
ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
# Generic build system uses -O2, we want -O3
-cflags-y += -O3
+# Note: No need to add to cflags-y as that happens anyways
+ARCH_CFLAGS += -O3
endif
# small data is default for elf32 tool-chain. If not usable, disable it
diff --git a/arch/arc/boot/dts/axc003.dtsi b/arch/arc/boot/dts/axc003.dtsi
index 15c8d62..1cd5e82 100644
--- a/arch/arc/boot/dts/axc003.dtsi
+++ b/arch/arc/boot/dts/axc003.dtsi
@@ -12,7 +12,7 @@
/ {
compatible = "snps,arc";
- clock-frequency = <75000000>;
+ clock-frequency = <90000000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arc/boot/dts/axc003_idu.dtsi b/arch/arc/boot/dts/axc003_idu.dtsi
index 199d428..2f0b332 100644
--- a/arch/arc/boot/dts/axc003_idu.dtsi
+++ b/arch/arc/boot/dts/axc003_idu.dtsi
@@ -12,7 +12,7 @@
/ {
compatible = "snps,arc";
- clock-frequency = <75000000>;
+ clock-frequency = <90000000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index 99fe118..57c1f33 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -50,8 +50,7 @@
* done for const @nr, but no code is generated due to gcc \
* const prop. \
*/ \
- if (__builtin_constant_p(nr)) \
- nr &= 0x1f; \
+ nr &= 0x1f; \
\
__asm__ __volatile__( \
"1: llock %0, [%1] \n" \
@@ -82,8 +81,7 @@
\
m += nr >> 5; \
\
- if (__builtin_constant_p(nr)) \
- nr &= 0x1f; \
+ nr &= 0x1f; \
\
/* \
* Explicit full memory barrier needed before/after as \
@@ -129,16 +127,13 @@
unsigned long temp, flags; \
m += nr >> 5; \
\
- if (__builtin_constant_p(nr)) \
- nr &= 0x1f; \
- \
/* \
* spin lock/unlock provide the needed smp_mb() before/after \
*/ \
bitops_lock(flags); \
\
temp = *m; \
- *m = temp c_op (1UL << nr); \
+ *m = temp c_op (1UL << (nr & 0x1f)); \
\
bitops_unlock(flags); \
}
@@ -149,17 +144,14 @@
unsigned long old, flags; \
m += nr >> 5; \
\
- if (__builtin_constant_p(nr)) \
- nr &= 0x1f; \
- \
bitops_lock(flags); \
\
old = *m; \
- *m = old c_op (1 << nr); \
+ *m = old c_op (1UL << (nr & 0x1f)); \
\
bitops_unlock(flags); \
\
- return (old & (1 << nr)) != 0; \
+ return (old & (1UL << (nr & 0x1f))) != 0; \
}
#endif /* CONFIG_ARC_HAS_LLSC */
@@ -174,11 +166,8 @@
unsigned long temp; \
m += nr >> 5; \
\
- if (__builtin_constant_p(nr)) \
- nr &= 0x1f; \
- \
temp = *m; \
- *m = temp c_op (1UL << nr); \
+ *m = temp c_op (1UL << (nr & 0x1f)); \
}
#define __TEST_N_BIT_OP(op, c_op, asm_op) \
@@ -187,13 +176,10 @@
unsigned long old; \
m += nr >> 5; \
\
- if (__builtin_constant_p(nr)) \
- nr &= 0x1f; \
- \
old = *m; \
- *m = old c_op (1 << nr); \
+ *m = old c_op (1UL << (nr & 0x1f)); \
\
- return (old & (1 << nr)) != 0; \
+ return (old & (1UL << (nr & 0x1f))) != 0; \
}
#define BIT_OPS(op, c_op, asm_op) \
@@ -224,10 +210,7 @@
addr += nr >> 5;
- if (__builtin_constant_p(nr))
- nr &= 0x1f;
-
- mask = 1 << nr;
+ mask = 1UL << (nr & 0x1f);
return ((mask & *addr) != 0);
}
diff --git a/arch/arc/include/asm/futex.h b/arch/arc/include/asm/futex.h
index 05b5aaf..70cfe16 100644
--- a/arch/arc/include/asm/futex.h
+++ b/arch/arc/include/asm/futex.h
@@ -16,12 +16,15 @@
#include <linux/uaccess.h>
#include <asm/errno.h>
+#ifdef CONFIG_ARC_HAS_LLSC
+
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)\
\
__asm__ __volatile__( \
- "1: ld %1, [%2] \n" \
+ "1: llock %1, [%2] \n" \
insn "\n" \
- "2: st %0, [%2] \n" \
+ "2: scond %0, [%2] \n" \
+ " bnz 1b \n" \
" mov %0, 0 \n" \
"3: \n" \
" .section .fixup,\"ax\" \n" \
@@ -39,6 +42,33 @@
: "r" (uaddr), "r" (oparg), "ir" (-EFAULT) \
: "cc", "memory")
+#else /* !CONFIG_ARC_HAS_LLSC */
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)\
+ \
+ __asm__ __volatile__( \
+ "1: ld %1, [%2] \n" \
+ insn "\n" \
+ "2: st %0, [%2] \n" \
+ " mov %0, 0 \n" \
+ "3: \n" \
+ " .section .fixup,\"ax\" \n" \
+ " .align 4 \n" \
+ "4: mov %0, %4 \n" \
+ " b 3b \n" \
+ " .previous \n" \
+ " .section __ex_table,\"a\" \n" \
+ " .align 4 \n" \
+ " .word 1b, 4b \n" \
+ " .word 2b, 4b \n" \
+ " .previous \n" \
+ \
+ : "=&r" (ret), "=&r" (oldval) \
+ : "r" (uaddr), "r" (oparg), "ir" (-EFAULT) \
+ : "cc", "memory")
+
+#endif
+
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
{
int op = (encoded_op >> 28) & 7;
@@ -123,11 +153,17 @@
pagefault_disable();
- /* TBD : can use llock/scond */
__asm__ __volatile__(
- "1: ld %0, [%3] \n"
- " brne %0, %1, 3f \n"
- "2: st %2, [%3] \n"
+#ifdef CONFIG_ARC_HAS_LLSC
+ "1: llock %0, [%3] \n"
+ " brne %0, %1, 3f \n"
+ "2: scond %2, [%3] \n"
+ " bnz 1b \n"
+#else
+ "1: ld %0, [%3] \n"
+ " brne %0, %1, 3f \n"
+ "2: st %2, [%3] \n"
+#endif
"3: \n"
" .section .fixup,\"ax\" \n"
"4: mov %0, %4 \n"
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 9175597..91694ec 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -106,7 +106,7 @@
long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13;
};
-#define instruction_pointer(regs) ((regs)->ret)
+#define instruction_pointer(regs) (unsigned long)((regs)->ret)
#define profile_pc(regs) instruction_pointer(regs)
/* return 1 if user mode or 0 if kernel mode */
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 6208c63..26c1568 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -12,7 +12,6 @@
#include <linux/of.h>
#include <linux/irqdomain.h>
#include <linux/irqchip.h>
-#include "../../drivers/irqchip/irqchip.h"
#include <asm/irq.h>
/*
diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c
index fcdddb6..039fac3 100644
--- a/arch/arc/kernel/intc-compact.c
+++ b/arch/arc/kernel/intc-compact.c
@@ -12,7 +12,6 @@
#include <linux/of.h>
#include <linux/irqdomain.h>
#include <linux/irqchip.h>
-#include "../../drivers/irqchip/irqchip.h"
#include <asm/irq.h>
/*
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 30284e8..2fb8658 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -175,7 +175,6 @@
#include <linux/irqchip.h>
#include <linux/of.h>
#include <linux/of_irq.h>
-#include "../../drivers/irqchip/irqchip.h"
/*
* Set the DEST for @cmn_irq to @cpu_mask (1 bit per core)
@@ -218,11 +217,28 @@
raw_spin_unlock_irqrestore(&mcip_lock, flags);
}
+#ifdef CONFIG_SMP
static int
-idu_irq_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool f)
+idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
+ bool force)
{
+ unsigned long flags;
+ cpumask_t online;
+
+ /* errout if no online cpu per @cpumask */
+ if (!cpumask_and(&online, cpumask, cpu_online_mask))
+ return -EINVAL;
+
+ raw_spin_lock_irqsave(&mcip_lock, flags);
+
+ idu_set_dest(data->hwirq, cpumask_bits(&online)[0]);
+ idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
+
+ raw_spin_unlock_irqrestore(&mcip_lock, flags);
+
return IRQ_SET_MASK_OK;
}
+#endif
static struct irq_chip idu_irq_chip = {
.name = "MCIP IDU Intc",
@@ -330,8 +346,7 @@
if (!i)
idu_first_irq = irq;
- irq_set_handler_data(irq, domain);
- irq_set_chained_handler(irq, idu_cascade_isr);
+ irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain);
}
__mcip_cmd(CMD_IDU_ENABLE, 0);
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index a3d1862..18cc015 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -142,17 +142,22 @@
}
static const struct cpuinfo_data arc_cpu_tbl[] = {
+#ifdef CONFIG_ISA_ARCOMPACT
{ {0x20, "ARC 600" }, 0x2F},
{ {0x30, "ARC 700" }, 0x33},
{ {0x34, "ARC 700 R4.10"}, 0x34},
{ {0x35, "ARC 700 R4.11"}, 0x35},
- { {0x50, "ARC HS38" }, 0x51},
+#else
+ { {0x50, "ARC HS38 R2.0"}, 0x51},
+ { {0x52, "ARC HS38 R2.1"}, 0x52},
+#endif
{ {0x00, NULL } }
};
-#define IS_AVAIL1(v, str) ((v) ? str : "")
-#define IS_USED(cfg) (IS_ENABLED(cfg) ? "" : "(not used) ")
-#define IS_AVAIL2(v, str, cfg) IS_AVAIL1(v, str), IS_AVAIL1(v, IS_USED(cfg))
+#define IS_AVAIL1(v, s) ((v) ? s : "")
+#define IS_USED_RUN(v) ((v) ? "" : "(not used) ")
+#define IS_USED_CFG(cfg) IS_USED_RUN(IS_ENABLED(cfg))
+#define IS_AVAIL2(v, s, cfg) IS_AVAIL1(v, s), IS_AVAIL1(v, IS_USED_CFG(cfg))
static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
{
@@ -226,7 +231,7 @@
n += scnprintf(buf + n, len - n, "mpy[opt %d] ", opt);
}
n += scnprintf(buf + n, len - n, "%s",
- IS_USED(CONFIG_ARC_HAS_HW_MPY));
+ IS_USED_CFG(CONFIG_ARC_HAS_HW_MPY));
}
n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n",
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 807f7d6..a6f91e8 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -58,7 +58,6 @@
static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
{
- struct path path;
char *path_nm = NULL;
struct mm_struct *mm;
struct file *exe_file;
diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c
index b29d62e..1cd6695 100644
--- a/arch/arc/mm/cache.c
+++ b/arch/arc/mm/cache.c
@@ -468,10 +468,18 @@
noinline void slc_op(unsigned long paddr, unsigned long sz, const int op)
{
#ifdef CONFIG_ISA_ARCV2
+ /*
+ * SLC is shared between all cores and concurrent aux operations from
+ * multiple cores need to be serialized using a spinlock
+ * A concurrent operation can be silently ignored and/or the old/new
+ * operation can remain incomplete forever (lockup in SLC_CTRL_BUSY loop
+ * below)
+ */
+ static DEFINE_SPINLOCK(lock);
unsigned long flags;
unsigned int ctrl;
- local_irq_save(flags);
+ spin_lock_irqsave(&lock, flags);
/*
* The Region Flush operation is specified by CTRL.RGN_OP[11..9]
@@ -504,7 +512,7 @@
while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lock, flags);
#endif
}
diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index 74a637a..57706a9 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -60,8 +60,8 @@
/* This is kernel Virtual address (0x7000_0000 based) */
kvaddr = ioremap_nocache((unsigned long)paddr, size);
- if (kvaddr != NULL)
- memset(kvaddr, 0, size);
+ if (kvaddr == NULL)
+ return NULL;
/* This is bus address, platform dependent */
*dma_handle = (dma_addr_t)paddr;
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index aa46590..096f68b 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -686,7 +686,8 @@
&dcan1 {
status = "ok";
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&dcan1_pins_default>;
+ pinctrl-names = "default", "sleep", "active";
+ pinctrl-0 = <&dcan1_pins_sleep>;
pinctrl-1 = <&dcan1_pins_sleep>;
+ pinctrl-2 = <&dcan1_pins_default>;
};
diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts
index 4e1b605..8037384 100644
--- a/arch/arm/boot/dts/dra72-evm.dts
+++ b/arch/arm/boot/dts/dra72-evm.dts
@@ -587,9 +587,10 @@
&dcan1 {
status = "ok";
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&dcan1_pins_default>;
+ pinctrl-names = "default", "sleep", "active";
+ pinctrl-0 = <&dcan1_pins_sleep>;
pinctrl-1 = <&dcan1_pins_sleep>;
+ pinctrl-2 = <&dcan1_pins_default>;
};
&qspi {
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index 33013df..c496d48 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -125,6 +125,13 @@
if COLDFIRE
+choice
+ prompt "ColdFire SoC type"
+ default M520x
+ help
+ Select the type of ColdFire System-on-Chip (SoC) that you want
+ to build for.
+
config M5206
bool "MCF5206"
depends on !MMU
@@ -174,9 +181,6 @@
help
Freescale (Motorola) Coldfire 5251/5253 processor support.
-config M527x
- bool
-
config M5271
bool "MCF5271"
depends on !MMU
@@ -223,9 +227,6 @@
help
Motorola ColdFire 5307 processor support.
-config M53xx
- bool
-
config M532x
bool "MCF532x"
depends on !MMU
@@ -251,9 +252,6 @@
help
Motorola ColdFire 5407 processor support.
-config M54xx
- bool
-
config M547x
bool "MCF547x"
select M54xx
@@ -280,6 +278,17 @@
help
Freescale Coldfire 54410/54415/54416/54417/54418 processor support.
+endchoice
+
+config M527x
+ bool
+
+config M53xx
+ bool
+
+config M54xx
+ bool
+
endif # COLDFIRE
@@ -416,22 +425,18 @@
config HAVE_IPSBAR
bool
-config CLOCK_SET
- bool "Enable setting the CPU clock frequency"
- depends on COLDFIRE
- default n
- help
- On some CPU's you do not need to know what the core CPU clock
- frequency is. On these you can disable clock setting. On some
- traditional 68K parts, and on all ColdFire parts you need to set
- the appropriate CPU clock frequency. On these devices many of the
- onboard peripherals derive their timing from the master CPU clock
- frequency.
-
config CLOCK_FREQ
int "Set the core clock frequency"
+ default "25000000" if M5206
+ default "54000000" if M5206e
+ default "166666666" if M520x
+ default "140000000" if M5249
+ default "150000000" if M527x || M523x
+ default "90000000" if M5307
+ default "50000000" if M5407
+ default "266000000" if M54xx
default "66666666"
- depends on CLOCK_SET
+ depends on COLDFIRE
help
Define the CPU clock frequency in use. This is the core clock
frequency, it may or may not be the same as the external clock
diff --git a/arch/m68k/configs/m5208evb_defconfig b/arch/m68k/configs/m5208evb_defconfig
index e7292f4..4c7b793 100644
--- a/arch/m68k/configs/m5208evb_defconfig
+++ b/arch/m68k/configs/m5208evb_defconfig
@@ -1,10 +1,6 @@
-# CONFIG_MMU is not set
-CONFIG_EXPERIMENTAL=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
@@ -16,17 +12,12 @@
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
-CONFIG_M520x=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=166666666
-CONFIG_CLOCK_DIV=2
-CONFIG_M5208EVB=y
+# CONFIG_MMU is not set
# CONFIG_4KSTACKS is not set
CONFIG_RAMBASE=0x40000000
CONFIG_RAMSIZE=0x2000000
CONFIG_VECTORBASE=0x40000000
CONFIG_KERNELBASE=0x40020000
-CONFIG_RAM16BIT=y
CONFIG_BINFMT_FLAT=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -40,24 +31,19 @@
# CONFIG_IPV6 is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAM=y
CONFIG_MTD_UCLINUX=y
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_BAUDRATE=115200
CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
@@ -68,8 +54,6 @@
CONFIG_ROMFS_FS=y
CONFIG_ROMFS_BACKED_BY_MTD=y
# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_FULLDEBUG=y
CONFIG_BOOTPARAM=y
CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
+CONFIG_FULLDEBUG=y
diff --git a/arch/m68k/configs/m5249evb_defconfig b/arch/m68k/configs/m5249evb_defconfig
index 0cd4b39..a782f36 100644
--- a/arch/m68k/configs/m5249evb_defconfig
+++ b/arch/m68k/configs/m5249evb_defconfig
@@ -1,10 +1,6 @@
-# CONFIG_MMU is not set
-CONFIG_EXPERIMENTAL=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
@@ -16,10 +12,8 @@
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_MMU is not set
CONFIG_M5249=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=140000000
-CONFIG_CLOCK_DIV=2
CONFIG_M5249C3=y
CONFIG_RAMBASE=0x00000000
CONFIG_RAMSIZE=0x00800000
@@ -38,23 +32,18 @@
# CONFIG_IPV6 is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAM=y
CONFIG_MTD_UCLINUX=y
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
CONFIG_PPP=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_EXT2_FS=y
@@ -62,7 +51,5 @@
CONFIG_ROMFS_FS=y
CONFIG_ROMFS_BACKED_BY_MTD=y
# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_BOOTPARAM=y
CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
-# CONFIG_CRC32 is not set
diff --git a/arch/m68k/configs/m5272c3_defconfig b/arch/m68k/configs/m5272c3_defconfig
index a60cb35..6f5fb92 100644
--- a/arch/m68k/configs/m5272c3_defconfig
+++ b/arch/m68k/configs/m5272c3_defconfig
@@ -1,10 +1,6 @@
-# CONFIG_MMU is not set
-CONFIG_EXPERIMENTAL=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
@@ -16,8 +12,8 @@
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_MMU is not set
CONFIG_M5272=y
-CONFIG_CLOCK_SET=y
CONFIG_M5272C3=y
CONFIG_RAMBASE=0x00000000
CONFIG_RAMSIZE=0x00800000
@@ -36,23 +32,18 @@
# CONFIG_IPV6 is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAM=y
CONFIG_MTD_UCLINUX=y
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_EXT2_FS=y
@@ -61,6 +52,5 @@
CONFIG_ROMFS_FS=y
CONFIG_ROMFS_BACKED_BY_MTD=y
# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_BOOTPARAM=y
CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
diff --git a/arch/m68k/configs/m5275evb_defconfig b/arch/m68k/configs/m5275evb_defconfig
index e6502ab..b5d7cd1 100644
--- a/arch/m68k/configs/m5275evb_defconfig
+++ b/arch/m68k/configs/m5275evb_defconfig
@@ -1,10 +1,6 @@
-# CONFIG_MMU is not set
-CONFIG_EXPERIMENTAL=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
@@ -16,11 +12,8 @@
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_MMU is not set
CONFIG_M5275=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=150000000
-CONFIG_CLOCK_DIV=2
-CONFIG_M5275EVB=y
# CONFIG_4KSTACKS is not set
CONFIG_RAMBASE=0x00000000
CONFIG_RAMSIZE=0x00000000
@@ -39,24 +32,19 @@
# CONFIG_IPV6 is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAM=y
CONFIG_MTD_UCLINUX=y
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
CONFIG_PPP=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_EXT2_FS=y
@@ -65,8 +53,5 @@
CONFIG_ROMFS_FS=y
CONFIG_ROMFS_BACKED_BY_MTD=y
# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_BOOTPARAM=y
CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
-# CONFIG_CRC32 is not set
diff --git a/arch/m68k/configs/m5307c3_defconfig b/arch/m68k/configs/m5307c3_defconfig
index 023812a..1b4c094 100644
--- a/arch/m68k/configs/m5307c3_defconfig
+++ b/arch/m68k/configs/m5307c3_defconfig
@@ -1,10 +1,6 @@
-# CONFIG_MMU is not set
-CONFIG_EXPERIMENTAL=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
@@ -16,10 +12,8 @@
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_MMU is not set
CONFIG_M5307=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=90000000
-CONFIG_CLOCK_DIV=2
CONFIG_M5307C3=y
CONFIG_RAMBASE=0x00000000
CONFIG_RAMSIZE=0x00800000
@@ -38,16 +32,11 @@
# CONFIG_IPV6 is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAM=y
CONFIG_MTD_UCLINUX=y
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
CONFIG_PPP=y
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
@@ -56,21 +45,17 @@
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_EXT2_FS=y
# CONFIG_DNOTIFY is not set
CONFIG_ROMFS_FS=y
CONFIG_ROMFS_BACKED_BY_MTD=y
# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_FULLDEBUG=y
CONFIG_BOOTPARAM=y
CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
-# CONFIG_CRC32 is not set
+CONFIG_FULLDEBUG=y
diff --git a/arch/m68k/configs/m5407c3_defconfig b/arch/m68k/configs/m5407c3_defconfig
index 557b39f..275ad543 100644
--- a/arch/m68k/configs/m5407c3_defconfig
+++ b/arch/m68k/configs/m5407c3_defconfig
@@ -1,10 +1,6 @@
-# CONFIG_MMU is not set
-CONFIG_EXPERIMENTAL=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
@@ -17,9 +13,8 @@
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_MMU is not set
CONFIG_M5407=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=50000000
CONFIG_M5407C3=y
CONFIG_RAMBASE=0x00000000
CONFIG_RAMSIZE=0x00000000
@@ -38,22 +33,17 @@
# CONFIG_IPV6 is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAM=y
CONFIG_MTD_UCLINUX=y
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
CONFIG_PPP=y
# CONFIG_INPUT is not set
# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
CONFIG_SERIAL_MCF=y
CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
@@ -63,8 +53,5 @@
CONFIG_ROMFS_FS=y
CONFIG_ROMFS_BACKED_BY_MTD=y
# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_BOOTPARAM=y
CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
-# CONFIG_CRC32 is not set
diff --git a/arch/m68k/configs/m5475evb_defconfig b/arch/m68k/configs/m5475evb_defconfig
index c5018a6..4f4ccd13 100644
--- a/arch/m68k/configs/m5475evb_defconfig
+++ b/arch/m68k/configs/m5475evb_defconfig
@@ -1,11 +1,7 @@
-CONFIG_EXPERIMENTAL=y
# CONFIG_SWAP is not set
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SIGNALFD is not set
@@ -20,19 +16,16 @@
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_COLDFIRE=y
-CONFIG_M547x=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=266000000
# CONFIG_4KSTACKS is not set
CONFIG_RAMBASE=0x0
CONFIG_RAMSIZE=0x2000000
CONFIG_VECTORBASE=0x0
CONFIG_MBAR=0xff000000
CONFIG_KERNELBASE=0x20000
+CONFIG_PCI=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
diff --git a/arch/m68k/include/asm/coldfire.h b/arch/m68k/include/asm/coldfire.h
index c94557b..50aa4da 100644
--- a/arch/m68k/include/asm/coldfire.h
+++ b/arch/m68k/include/asm/coldfire.h
@@ -19,7 +19,7 @@
* in any case new boards come along from time to time that have yet
* another different clocking frequency.
*/
-#ifdef CONFIG_CLOCK_SET
+#ifdef CONFIG_CLOCK_FREQ
#define MCF_CLK CONFIG_CLOCK_FREQ
#else
#error "Don't know what your ColdFire CPU clock frequency is??"
diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index 618c85d3..f55cad5 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -413,7 +413,8 @@
#define writew(val, addr) out_le16((addr), (val))
#endif /* CONFIG_ATARI_ROM_ISA */
-#if !defined(CONFIG_ISA) && !defined(CONFIG_ATARI_ROM_ISA)
+#if !defined(CONFIG_ISA) && !defined(CONFIG_ATARI_ROM_ISA) && \
+ !(defined(CONFIG_PCI) && defined(CONFIG_COLDFIRE))
/*
* We need to define dummy functions for GENERIC_IOMAP support.
*/
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
index cfad7fca..d7697ab 100644
--- a/arch/s390/include/asm/ctl_reg.h
+++ b/arch/s390/include/asm/ctl_reg.h
@@ -57,7 +57,10 @@
unsigned long lap : 1; /* Low-address-protection control */
unsigned long : 4;
unsigned long edat : 1; /* Enhanced-DAT-enablement control */
- unsigned long : 23;
+ unsigned long : 4;
+ unsigned long afp : 1; /* AFP-register control */
+ unsigned long vx : 1; /* Vector enablement control */
+ unsigned long : 17;
};
};
diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h
index 4cb19fe..f897ec7 100644
--- a/arch/s390/include/asm/perf_event.h
+++ b/arch/s390/include/asm/perf_event.h
@@ -87,7 +87,15 @@
} __packed;
/* Perf hardware reserve and release functions */
+#ifdef CONFIG_PERF_EVENTS
int perf_reserve_sampling(void);
void perf_release_sampling(void);
+#else /* CONFIG_PERF_EVENTS */
+static inline int perf_reserve_sampling(void)
+{
+ return 0;
+}
+static inline void perf_release_sampling(void) {}
+#endif /* CONFIG_PERF_EVENTS */
#endif /* _ASM_S390_PERF_EVENT_H */
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index 505c17c..56b5508 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -21,6 +21,7 @@
#include <asm/nmi.h>
#include <asm/crw.h>
#include <asm/switch_to.h>
+#include <asm/ctl_reg.h>
struct mcck_struct {
int kill_task;
@@ -129,26 +130,30 @@
} else
asm volatile("lfpc 0(%0)" : : "a" (fpt_creg_save_area));
- asm volatile(
- " ld 0,0(%0)\n"
- " ld 1,8(%0)\n"
- " ld 2,16(%0)\n"
- " ld 3,24(%0)\n"
- " ld 4,32(%0)\n"
- " ld 5,40(%0)\n"
- " ld 6,48(%0)\n"
- " ld 7,56(%0)\n"
- " ld 8,64(%0)\n"
- " ld 9,72(%0)\n"
- " ld 10,80(%0)\n"
- " ld 11,88(%0)\n"
- " ld 12,96(%0)\n"
- " ld 13,104(%0)\n"
- " ld 14,112(%0)\n"
- " ld 15,120(%0)\n"
- : : "a" (fpt_save_area));
- /* Revalidate vector registers */
- if (MACHINE_HAS_VX && current->thread.vxrs) {
+ if (!MACHINE_HAS_VX) {
+ /* Revalidate floating point registers */
+ asm volatile(
+ " ld 0,0(%0)\n"
+ " ld 1,8(%0)\n"
+ " ld 2,16(%0)\n"
+ " ld 3,24(%0)\n"
+ " ld 4,32(%0)\n"
+ " ld 5,40(%0)\n"
+ " ld 6,48(%0)\n"
+ " ld 7,56(%0)\n"
+ " ld 8,64(%0)\n"
+ " ld 9,72(%0)\n"
+ " ld 10,80(%0)\n"
+ " ld 11,88(%0)\n"
+ " ld 12,96(%0)\n"
+ " ld 13,104(%0)\n"
+ " ld 14,112(%0)\n"
+ " ld 15,120(%0)\n"
+ : : "a" (fpt_save_area));
+ } else {
+ /* Revalidate vector registers */
+ union ctlreg0 cr0;
+
if (!mci->vr) {
/*
* Vector registers can't be restored and therefore
@@ -156,8 +161,12 @@
*/
kill_task = 1;
}
+ cr0.val = S390_lowcore.cregs_save_area[0];
+ cr0.afp = cr0.vx = 1;
+ __ctl_load(cr0.val, 0, 0);
restore_vx_regs((__vector128 *)
- S390_lowcore.vector_save_area_addr);
+ &S390_lowcore.vector_save_area);
+ __ctl_load(S390_lowcore.cregs_save_area[0], 0, 0);
}
/* Revalidate access registers */
asm volatile(
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index dc5edc2..8f587d8 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -163,7 +163,7 @@
asmlinkage void execve_tail(void)
{
current->thread.fp_regs.fpc = 0;
- asm volatile("sfpc %0,%0" : : "d" (0));
+ asm volatile("sfpc %0" : : "d" (0));
}
/*
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
index 43c3169..ada0c07 100644
--- a/arch/s390/kernel/sclp.S
+++ b/arch/s390/kernel/sclp.S
@@ -270,6 +270,8 @@
jno .Lesa2
ahi %r15,-80
stmh %r6,%r15,96(%r15) # store upper register halves
+ basr %r13,0
+ lmh %r0,%r15,.Lzeroes-.(%r13) # clear upper register halves
.Lesa2:
lr %r10,%r2 # save string pointer
lhi %r2,0
@@ -291,6 +293,8 @@
.Lesa3:
lm %r6,%r15,120(%r15) # restore registers
br %r14
+.Lzeroes:
+ .fill 64,4,0
.LwritedataS4:
.long 0x00760005 # SCLP command for write data
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index bc927a0..9cfa2ff 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/module.h>
#include <asm/processor.h>
+#include <asm/perf_event.h>
#include "../../../drivers/oprofile/oprof.h"
diff --git a/arch/x86/include/asm/intel_pmc_ipc.h b/arch/x86/include/asm/intel_pmc_ipc.h
index 200ec2e..cd0310e 100644
--- a/arch/x86/include/asm/intel_pmc_ipc.h
+++ b/arch/x86/include/asm/intel_pmc_ipc.h
@@ -25,36 +25,9 @@
#if IS_ENABLED(CONFIG_INTEL_PMC_IPC)
-/*
- * intel_pmc_ipc_simple_command
- * @cmd: command
- * @sub: sub type
- */
int intel_pmc_ipc_simple_command(int cmd, int sub);
-
-/*
- * intel_pmc_ipc_raw_cmd
- * @cmd: command
- * @sub: sub type
- * @in: input data
- * @inlen: input length in bytes
- * @out: output data
- * @outlen: output length in dwords
- * @sptr: data writing to SPTR register
- * @dptr: data writing to DPTR register
- */
int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
u32 *out, u32 outlen, u32 dptr, u32 sptr);
-
-/*
- * intel_pmc_ipc_command
- * @cmd: command
- * @sub: sub type
- * @in: input data
- * @inlen: input length in bytes
- * @out: output data
- * @outlen: output length in dwords
- */
int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
u32 *out, u32 outlen);
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 2a7f5d7..49ec903 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -604,6 +604,8 @@
bool iommu_noncoherent;
#define __KVM_HAVE_ARCH_NONCOHERENT_DMA
atomic_t noncoherent_dma_count;
+#define __KVM_HAVE_ARCH_ASSIGNED_DEVICE
+ atomic_t assigned_device_count;
struct kvm_pic *vpic;
struct kvm_ioapic *vioapic;
struct kvm_pit *vpit;
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
index 8fba544..f36d56b 100644
--- a/arch/x86/include/uapi/asm/hyperv.h
+++ b/arch/x86/include/uapi/asm/hyperv.h
@@ -108,6 +108,8 @@
#define HV_X64_HYPERCALL_PARAMS_XMM_AVAILABLE (1 << 4)
/* Support for a virtual guest idle state is available */
#define HV_X64_GUEST_IDLE_STATE_AVAILABLE (1 << 5)
+/* Guest crash data handler available */
+#define HV_X64_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
/*
* Implementation recommendations. Indicates which behaviors the hypervisor
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 64dd467..2fbea25 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -98,6 +98,8 @@
best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
vcpu->arch.eager_fpu = use_eager_fpu() || guest_cpuid_has_mpx(vcpu);
+ if (vcpu->arch.eager_fpu)
+ kvm_x86_ops->fpu_activate(vcpu);
/*
* The existing code assumes virtual address is 48-bit in the canonical
diff --git a/arch/x86/kvm/iommu.c b/arch/x86/kvm/iommu.c
index 7dbced3..5c520eb 100644
--- a/arch/x86/kvm/iommu.c
+++ b/arch/x86/kvm/iommu.c
@@ -200,6 +200,7 @@
goto out_unmap;
}
+ kvm_arch_start_assignment(kvm);
pci_set_dev_assigned(pdev);
dev_info(&pdev->dev, "kvm assign device\n");
@@ -224,6 +225,7 @@
iommu_detach_device(domain, &pdev->dev);
pci_clear_dev_assigned(pdev);
+ kvm_arch_end_assignment(kvm);
dev_info(&pdev->dev, "kvm deassign device\n");
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index f807496..4417146 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2479,6 +2479,14 @@
return 0;
}
+static bool kvm_is_mmio_pfn(pfn_t pfn)
+{
+ if (pfn_valid(pfn))
+ return !is_zero_pfn(pfn) && PageReserved(pfn_to_page(pfn));
+
+ return true;
+}
+
static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
unsigned pte_access, int level,
gfn_t gfn, pfn_t pfn, bool speculative,
@@ -2506,7 +2514,7 @@
spte |= PT_PAGE_SIZE_MASK;
if (tdp_enabled)
spte |= kvm_x86_ops->get_mt_mask(vcpu, gfn,
- kvm_is_reserved_pfn(pfn));
+ kvm_is_mmio_pfn(pfn));
if (host_writable)
spte |= SPTE_HOST_WRITEABLE;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 602b974..bbc678a 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -865,6 +865,64 @@
set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 0, 0);
}
+#define MTRR_TYPE_UC_MINUS 7
+#define MTRR2PROTVAL_INVALID 0xff
+
+static u8 mtrr2protval[8];
+
+static u8 fallback_mtrr_type(int mtrr)
+{
+ /*
+ * WT and WP aren't always available in the host PAT. Treat
+ * them as UC and UC- respectively. Everything else should be
+ * there.
+ */
+ switch (mtrr)
+ {
+ case MTRR_TYPE_WRTHROUGH:
+ return MTRR_TYPE_UNCACHABLE;
+ case MTRR_TYPE_WRPROT:
+ return MTRR_TYPE_UC_MINUS;
+ default:
+ BUG();
+ }
+}
+
+static void build_mtrr2protval(void)
+{
+ int i;
+ u64 pat;
+
+ for (i = 0; i < 8; i++)
+ mtrr2protval[i] = MTRR2PROTVAL_INVALID;
+
+ /* Ignore the invalid MTRR types. */
+ mtrr2protval[2] = 0;
+ mtrr2protval[3] = 0;
+
+ /*
+ * Use host PAT value to figure out the mapping from guest MTRR
+ * values to nested page table PAT/PCD/PWT values. We do not
+ * want to change the host PAT value every time we enter the
+ * guest.
+ */
+ rdmsrl(MSR_IA32_CR_PAT, pat);
+ for (i = 0; i < 8; i++) {
+ u8 mtrr = pat >> (8 * i);
+
+ if (mtrr2protval[mtrr] == MTRR2PROTVAL_INVALID)
+ mtrr2protval[mtrr] = __cm_idx2pte(i);
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (mtrr2protval[i] == MTRR2PROTVAL_INVALID) {
+ u8 fallback = fallback_mtrr_type(i);
+ mtrr2protval[i] = mtrr2protval[fallback];
+ BUG_ON(mtrr2protval[i] == MTRR2PROTVAL_INVALID);
+ }
+ }
+}
+
static __init int svm_hardware_setup(void)
{
int cpu;
@@ -931,6 +989,7 @@
} else
kvm_disable_tdp();
+ build_mtrr2protval();
return 0;
err:
@@ -1085,6 +1144,39 @@
return target_tsc - tsc;
}
+static void svm_set_guest_pat(struct vcpu_svm *svm, u64 *g_pat)
+{
+ struct kvm_vcpu *vcpu = &svm->vcpu;
+
+ /* Unlike Intel, AMD takes the guest's CR0.CD into account.
+ *
+ * AMD does not have IPAT. To emulate it for the case of guests
+ * with no assigned devices, just set everything to WB. If guests
+ * have assigned devices, however, we cannot force WB for RAM
+ * pages only, so use the guest PAT directly.
+ */
+ if (!kvm_arch_has_assigned_device(vcpu->kvm))
+ *g_pat = 0x0606060606060606;
+ else
+ *g_pat = vcpu->arch.pat;
+}
+
+static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
+{
+ u8 mtrr;
+
+ /*
+ * 1. MMIO: trust guest MTRR, so same as item 3.
+ * 2. No passthrough: always map as WB, and force guest PAT to WB as well
+ * 3. Passthrough: can't guarantee the result, try to trust guest.
+ */
+ if (!is_mmio && !kvm_arch_has_assigned_device(vcpu->kvm))
+ return 0;
+
+ mtrr = kvm_mtrr_get_guest_memory_type(vcpu, gfn);
+ return mtrr2protval[mtrr];
+}
+
static void init_vmcb(struct vcpu_svm *svm, bool init_event)
{
struct vmcb_control_area *control = &svm->vmcb->control;
@@ -1180,6 +1272,7 @@
clr_cr_intercept(svm, INTERCEPT_CR3_READ);
clr_cr_intercept(svm, INTERCEPT_CR3_WRITE);
save->g_pat = svm->vcpu.arch.pat;
+ svm_set_guest_pat(svm, &save->g_pat);
save->cr3 = 0;
save->cr4 = 0;
}
@@ -3254,6 +3347,16 @@
case MSR_VM_IGNNE:
vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
break;
+ case MSR_IA32_CR_PAT:
+ if (npt_enabled) {
+ if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
+ return 1;
+ vcpu->arch.pat = data;
+ svm_set_guest_pat(svm, &svm->vmcb->save.g_pat);
+ mark_dirty(svm->vmcb, VMCB_NPT);
+ break;
+ }
+ /* fall through */
default:
return kvm_set_msr_common(vcpu, msr);
}
@@ -4088,11 +4191,6 @@
return true;
}
-static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
-{
- return 0;
-}
-
static void svm_cpuid_update(struct kvm_vcpu *vcpu)
{
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index e856dd5..5b4e938 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -8632,22 +8632,17 @@
u64 ipat = 0;
/* For VT-d and EPT combination
- * 1. MMIO: always map as UC
+ * 1. MMIO: guest may want to apply WC, trust it.
* 2. EPT with VT-d:
* a. VT-d without snooping control feature: can't guarantee the
- * result, try to trust guest.
+ * result, try to trust guest. So the same as item 1.
* b. VT-d with snooping control feature: snooping control feature of
* VT-d engine can guarantee the cache correctness. Just set it
* to WB to keep consistent with host. So the same as item 3.
* 3. EPT without VT-d: always map as WB and set IPAT=1 to keep
* consistent with host MTRR
*/
- if (is_mmio) {
- cache = MTRR_TYPE_UNCACHABLE;
- goto exit;
- }
-
- if (!kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
+ if (!is_mmio && !kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
ipat = VMX_EPT_IPAT_BIT;
cache = MTRR_TYPE_WRBACK;
goto exit;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bbaf44e..5ef2560 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3157,8 +3157,7 @@
cpuid_count(XSTATE_CPUID, index,
&size, &offset, &ecx, &edx);
memcpy(dest, src + offset, size);
- } else
- WARN_ON_ONCE(1);
+ }
valid -= feature;
}
@@ -7315,11 +7314,6 @@
vcpu = kvm_x86_ops->vcpu_create(kvm, id);
- /*
- * Activate fpu unconditionally in case the guest needs eager FPU. It will be
- * deactivated soon if it doesn't.
- */
- kvm_x86_ops->fpu_activate(vcpu);
return vcpu;
}
@@ -8218,6 +8212,24 @@
kvm_x86_ops->interrupt_allowed(vcpu);
}
+void kvm_arch_start_assignment(struct kvm *kvm)
+{
+ atomic_inc(&kvm->arch.assigned_device_count);
+}
+EXPORT_SYMBOL_GPL(kvm_arch_start_assignment);
+
+void kvm_arch_end_assignment(struct kvm *kvm)
+{
+ atomic_dec(&kvm->arch.assigned_device_count);
+}
+EXPORT_SYMBOL_GPL(kvm_arch_end_assignment);
+
+bool kvm_arch_has_assigned_device(struct kvm *kvm)
+{
+ return atomic_read(&kvm->arch.assigned_device_count);
+}
+EXPORT_SYMBOL_GPL(kvm_arch_has_assigned_device);
+
void kvm_arch_register_noncoherent_dma(struct kvm *kvm)
{
atomic_inc(&kvm->arch.noncoherent_dma_count);
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index 0436c21..719b715 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -51,7 +51,7 @@
unsigned long idx = BIO_POOL_NONE;
unsigned inline_vecs;
- if (!bs) {
+ if (!bs || !bs->bio_integrity_pool) {
bip = kmalloc(sizeof(struct bio_integrity_payload) +
sizeof(struct bio_vec) * nr_vecs, gfp_mask);
inline_vecs = nr_vecs;
@@ -104,7 +104,7 @@
kfree(page_address(bip->bip_vec->bv_page) +
bip->bip_vec->bv_offset);
- if (bs) {
+ if (bs && bs->bio_integrity_pool) {
if (bip->bip_slab != BIO_POOL_NONE)
bvec_free(bs->bvec_integrity_pool, bip->bip_vec,
bip->bip_slab);
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 9f97da5..9da02c0 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -29,6 +29,14 @@
#define MAX_KEY_LEN 100
+/*
+ * blkcg_pol_mutex protects blkcg_policy[] and policy [de]activation.
+ * blkcg_pol_register_mutex nests outside of it and synchronizes entire
+ * policy [un]register operations including cgroup file additions /
+ * removals. Putting cgroup file registration outside blkcg_pol_mutex
+ * allows grabbing it from cgroup callbacks.
+ */
+static DEFINE_MUTEX(blkcg_pol_register_mutex);
static DEFINE_MUTEX(blkcg_pol_mutex);
struct blkcg blkcg_root;
@@ -38,6 +46,8 @@
static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS];
+static LIST_HEAD(all_blkcgs); /* protected by blkcg_pol_mutex */
+
static bool blkcg_policy_enabled(struct request_queue *q,
const struct blkcg_policy *pol)
{
@@ -453,20 +463,7 @@
struct blkcg_gq *blkg;
int i;
- /*
- * XXX: We invoke cgroup_add/rm_cftypes() under blkcg_pol_mutex
- * which ends up putting cgroup's internal cgroup_tree_mutex under
- * it; however, cgroup_tree_mutex is nested above cgroup file
- * active protection and grabbing blkcg_pol_mutex from a cgroup
- * file operation creates a possible circular dependency. cgroup
- * internal locking is planned to go through further simplification
- * and this issue should go away soon. For now, let's trylock
- * blkcg_pol_mutex and restart the write on failure.
- *
- * http://lkml.kernel.org/g/5363C04B.4010400@oracle.com
- */
- if (!mutex_trylock(&blkcg_pol_mutex))
- return restart_syscall();
+ mutex_lock(&blkcg_pol_mutex);
spin_lock_irq(&blkcg->lock);
/*
@@ -822,8 +819,17 @@
{
struct blkcg *blkcg = css_to_blkcg(css);
- if (blkcg != &blkcg_root)
+ mutex_lock(&blkcg_pol_mutex);
+ list_del(&blkcg->all_blkcgs_node);
+ mutex_unlock(&blkcg_pol_mutex);
+
+ if (blkcg != &blkcg_root) {
+ int i;
+
+ for (i = 0; i < BLKCG_MAX_POLS; i++)
+ kfree(blkcg->pd[i]);
kfree(blkcg);
+ }
}
static struct cgroup_subsys_state *
@@ -833,6 +839,8 @@
struct cgroup_subsys_state *ret;
int i;
+ mutex_lock(&blkcg_pol_mutex);
+
if (!parent_css) {
blkcg = &blkcg_root;
goto done;
@@ -875,14 +883,17 @@
#ifdef CONFIG_CGROUP_WRITEBACK
INIT_LIST_HEAD(&blkcg->cgwb_list);
#endif
+ list_add_tail(&blkcg->all_blkcgs_node, &all_blkcgs);
+
+ mutex_unlock(&blkcg_pol_mutex);
return &blkcg->css;
free_pd_blkcg:
for (i--; i >= 0; i--)
kfree(blkcg->pd[i]);
-
free_blkcg:
kfree(blkcg);
+ mutex_unlock(&blkcg_pol_mutex);
return ret;
}
@@ -1037,10 +1048,8 @@
const struct blkcg_policy *pol)
{
LIST_HEAD(pds);
- LIST_HEAD(cpds);
struct blkcg_gq *blkg;
struct blkg_policy_data *pd, *nd;
- struct blkcg_policy_data *cpd, *cnd;
int cnt = 0, ret;
if (blkcg_policy_enabled(q, pol))
@@ -1053,10 +1062,7 @@
cnt++;
spin_unlock_irq(q->queue_lock);
- /*
- * Allocate per-blkg and per-blkcg policy data
- * for all existing blkgs.
- */
+ /* allocate per-blkg policy data for all existing blkgs */
while (cnt--) {
pd = kzalloc_node(pol->pd_size, GFP_KERNEL, q->node);
if (!pd) {
@@ -1064,15 +1070,6 @@
goto out_free;
}
list_add_tail(&pd->alloc_node, &pds);
-
- if (!pol->cpd_size)
- continue;
- cpd = kzalloc_node(pol->cpd_size, GFP_KERNEL, q->node);
- if (!cpd) {
- ret = -ENOMEM;
- goto out_free;
- }
- list_add_tail(&cpd->alloc_node, &cpds);
}
/*
@@ -1082,32 +1079,17 @@
spin_lock_irq(q->queue_lock);
list_for_each_entry(blkg, &q->blkg_list, q_node) {
- if (WARN_ON(list_empty(&pds)) ||
- WARN_ON(pol->cpd_size && list_empty(&cpds))) {
+ if (WARN_ON(list_empty(&pds))) {
/* umm... this shouldn't happen, just abort */
ret = -ENOMEM;
goto out_unlock;
}
- cpd = list_first_entry(&cpds, struct blkcg_policy_data,
- alloc_node);
- list_del_init(&cpd->alloc_node);
pd = list_first_entry(&pds, struct blkg_policy_data, alloc_node);
list_del_init(&pd->alloc_node);
/* grab blkcg lock too while installing @pd on @blkg */
spin_lock(&blkg->blkcg->lock);
- if (!pol->cpd_size)
- goto no_cpd;
- if (!blkg->blkcg->pd[pol->plid]) {
- /* Per-policy per-blkcg data */
- blkg->blkcg->pd[pol->plid] = cpd;
- cpd->plid = pol->plid;
- pol->cpd_init_fn(blkg->blkcg);
- } else { /* must free it as it has already been extracted */
- kfree(cpd);
- }
-no_cpd:
blkg->pd[pol->plid] = pd;
pd->blkg = blkg;
pd->plid = pol->plid;
@@ -1124,8 +1106,6 @@
blk_queue_bypass_end(q);
list_for_each_entry_safe(pd, nd, &pds, alloc_node)
kfree(pd);
- list_for_each_entry_safe(cpd, cnd, &cpds, alloc_node)
- kfree(cpd);
return ret;
}
EXPORT_SYMBOL_GPL(blkcg_activate_policy);
@@ -1162,8 +1142,6 @@
kfree(blkg->pd[pol->plid]);
blkg->pd[pol->plid] = NULL;
- kfree(blkg->blkcg->pd[pol->plid]);
- blkg->blkcg->pd[pol->plid] = NULL;
spin_unlock(&blkg->blkcg->lock);
}
@@ -1182,11 +1160,13 @@
*/
int blkcg_policy_register(struct blkcg_policy *pol)
{
+ struct blkcg *blkcg;
int i, ret;
if (WARN_ON(pol->pd_size < sizeof(struct blkg_policy_data)))
return -EINVAL;
+ mutex_lock(&blkcg_pol_register_mutex);
mutex_lock(&blkcg_pol_mutex);
/* find an empty slot */
@@ -1195,19 +1175,49 @@
if (!blkcg_policy[i])
break;
if (i >= BLKCG_MAX_POLS)
- goto out_unlock;
+ goto err_unlock;
- /* register and update blkgs */
+ /* register @pol */
pol->plid = i;
- blkcg_policy[i] = pol;
+ blkcg_policy[pol->plid] = pol;
+
+ /* allocate and install cpd's */
+ if (pol->cpd_size) {
+ list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) {
+ struct blkcg_policy_data *cpd;
+
+ cpd = kzalloc(pol->cpd_size, GFP_KERNEL);
+ if (!cpd) {
+ mutex_unlock(&blkcg_pol_mutex);
+ goto err_free_cpds;
+ }
+
+ blkcg->pd[pol->plid] = cpd;
+ cpd->plid = pol->plid;
+ pol->cpd_init_fn(blkcg);
+ }
+ }
+
+ mutex_unlock(&blkcg_pol_mutex);
/* everything is in place, add intf files for the new policy */
if (pol->cftypes)
WARN_ON(cgroup_add_legacy_cftypes(&blkio_cgrp_subsys,
pol->cftypes));
- ret = 0;
-out_unlock:
+ mutex_unlock(&blkcg_pol_register_mutex);
+ return 0;
+
+err_free_cpds:
+ if (pol->cpd_size) {
+ list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) {
+ kfree(blkcg->pd[pol->plid]);
+ blkcg->pd[pol->plid] = NULL;
+ }
+ }
+ blkcg_policy[pol->plid] = NULL;
+err_unlock:
mutex_unlock(&blkcg_pol_mutex);
+ mutex_unlock(&blkcg_pol_register_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(blkcg_policy_register);
@@ -1220,7 +1230,9 @@
*/
void blkcg_policy_unregister(struct blkcg_policy *pol)
{
- mutex_lock(&blkcg_pol_mutex);
+ struct blkcg *blkcg;
+
+ mutex_lock(&blkcg_pol_register_mutex);
if (WARN_ON(blkcg_policy[pol->plid] != pol))
goto out_unlock;
@@ -1229,9 +1241,19 @@
if (pol->cftypes)
cgroup_rm_cftypes(pol->cftypes);
- /* unregister and update blkgs */
+ /* remove cpds and unregister */
+ mutex_lock(&blkcg_pol_mutex);
+
+ if (pol->cpd_size) {
+ list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) {
+ kfree(blkcg->pd[pol->plid]);
+ blkcg->pd[pol->plid] = NULL;
+ }
+ }
blkcg_policy[pol->plid] = NULL;
-out_unlock:
+
mutex_unlock(&blkcg_pol_mutex);
+out_unlock:
+ mutex_unlock(&blkcg_pol_register_mutex);
}
EXPORT_SYMBOL_GPL(blkcg_policy_unregister);
diff --git a/block/blk-core.c b/block/blk-core.c
index 82819e6..627ed0c 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -3370,7 +3370,7 @@
int __init blk_dev_init(void)
{
BUILD_BUG_ON(__REQ_NR_BITS > 8 *
- sizeof(((struct request *)0)->cmd_flags));
+ FIELD_SIZEOF(struct request, cmd_flags));
/* used for unplugging and affects IO latency/throughput - HIGHPRI */
kblockd_workqueue = alloc_workqueue("kblockd",
diff --git a/block/blk-mq.c b/block/blk-mq.c
index f537796..7d842db 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1998,7 +1998,7 @@
goto err_hctxs;
setup_timer(&q->timeout, blk_mq_rq_timer, (unsigned long) q);
- blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30000);
+ blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);
q->nr_queues = nr_cpu_ids;
q->nr_hw_queues = set->nr_hw_queues;
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 8321430..08ac110 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -24,7 +24,7 @@
# Power management related files
acpi-y += wakeup.o
acpi-$(CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT) += sleep.o
-acpi-y += device_pm.o
+acpi-y += device_sysfs.o device_pm.o
acpi-$(CONFIG_ACPI_SLEEP) += proc.o
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 513e7230e..a23903c 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -423,6 +423,413 @@
acpi_evaluate_ost(handle, type, ost_code, NULL);
}
+static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct acpi_device *device = data;
+
+ device->driver->ops.notify(device, event);
+}
+
+static void acpi_device_notify_fixed(void *data)
+{
+ struct acpi_device *device = data;
+
+ /* Fixed hardware devices have no handles */
+ acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
+}
+
+static u32 acpi_device_fixed_event(void *data)
+{
+ acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
+ return ACPI_INTERRUPT_HANDLED;
+}
+
+static int acpi_device_install_notify_handler(struct acpi_device *device)
+{
+ acpi_status status;
+
+ if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
+ status =
+ acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_device_fixed_event,
+ device);
+ else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
+ status =
+ acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_device_fixed_event,
+ device);
+ else
+ status = acpi_install_notify_handler(device->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_device_notify,
+ device);
+
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+ return 0;
+}
+
+static void acpi_device_remove_notify_handler(struct acpi_device *device)
+{
+ if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
+ acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_device_fixed_event);
+ else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
+ acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_device_fixed_event);
+ else
+ acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+ acpi_device_notify);
+}
+
+/* --------------------------------------------------------------------------
+ Device Matching
+ -------------------------------------------------------------------------- */
+
+/**
+ * acpi_device_is_first_physical_node - Is given dev first physical node
+ * @adev: ACPI companion device
+ * @dev: Physical device to check
+ *
+ * Function checks if given @dev is the first physical devices attached to
+ * the ACPI companion device. This distinction is needed in some cases
+ * where the same companion device is shared between many physical devices.
+ *
+ * Note that the caller have to provide valid @adev pointer.
+ */
+bool acpi_device_is_first_physical_node(struct acpi_device *adev,
+ const struct device *dev)
+{
+ bool ret = false;
+
+ mutex_lock(&adev->physical_node_lock);
+ if (!list_empty(&adev->physical_node_list)) {
+ const struct acpi_device_physical_node *node;
+
+ node = list_first_entry(&adev->physical_node_list,
+ struct acpi_device_physical_node, node);
+ ret = node->dev == dev;
+ }
+ mutex_unlock(&adev->physical_node_lock);
+
+ return ret;
+}
+
+/*
+ * acpi_companion_match() - Can we match via ACPI companion device
+ * @dev: Device in question
+ *
+ * Check if the given device has an ACPI companion and if that companion has
+ * a valid list of PNP IDs, and if the device is the first (primary) physical
+ * device associated with it. Return the companion pointer if that's the case
+ * or NULL otherwise.
+ *
+ * If multiple physical devices are attached to a single ACPI companion, we need
+ * to be careful. The usage scenario for this kind of relationship is that all
+ * of the physical devices in question use resources provided by the ACPI
+ * companion. A typical case is an MFD device where all the sub-devices share
+ * the parent's ACPI companion. In such cases we can only allow the primary
+ * (first) physical device to be matched with the help of the companion's PNP
+ * IDs.
+ *
+ * Additional physical devices sharing the ACPI companion can still use
+ * resources available from it but they will be matched normally using functions
+ * provided by their bus types (and analogously for their modalias).
+ */
+struct acpi_device *acpi_companion_match(const struct device *dev)
+{
+ struct acpi_device *adev;
+ struct mutex *physical_node_lock;
+
+ adev = ACPI_COMPANION(dev);
+ if (!adev)
+ return NULL;
+
+ if (list_empty(&adev->pnp.ids))
+ return NULL;
+
+ physical_node_lock = &adev->physical_node_lock;
+ mutex_lock(physical_node_lock);
+ if (list_empty(&adev->physical_node_list)) {
+ adev = NULL;
+ } else {
+ const struct acpi_device_physical_node *node;
+
+ node = list_first_entry(&adev->physical_node_list,
+ struct acpi_device_physical_node, node);
+ if (node->dev != dev)
+ adev = NULL;
+ }
+ mutex_unlock(physical_node_lock);
+
+ return adev;
+}
+
+/**
+ * acpi_of_match_device - Match device object using the "compatible" property.
+ * @adev: ACPI device object to match.
+ * @of_match_table: List of device IDs to match against.
+ *
+ * If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of
+ * identifiers and a _DSD object with the "compatible" property, use that
+ * property to match against the given list of identifiers.
+ */
+static bool acpi_of_match_device(struct acpi_device *adev,
+ const struct of_device_id *of_match_table)
+{
+ const union acpi_object *of_compatible, *obj;
+ int i, nval;
+
+ if (!adev)
+ return false;
+
+ of_compatible = adev->data.of_compatible;
+ if (!of_match_table || !of_compatible)
+ return false;
+
+ if (of_compatible->type == ACPI_TYPE_PACKAGE) {
+ nval = of_compatible->package.count;
+ obj = of_compatible->package.elements;
+ } else { /* Must be ACPI_TYPE_STRING. */
+ nval = 1;
+ obj = of_compatible;
+ }
+ /* Now we can look for the driver DT compatible strings */
+ for (i = 0; i < nval; i++, obj++) {
+ const struct of_device_id *id;
+
+ for (id = of_match_table; id->compatible[0]; id++)
+ if (!strcasecmp(obj->string.pointer, id->compatible))
+ return true;
+ }
+
+ return false;
+}
+
+static bool __acpi_match_device_cls(const struct acpi_device_id *id,
+ struct acpi_hardware_id *hwid)
+{
+ int i, msk, byte_shift;
+ char buf[3];
+
+ if (!id->cls)
+ return false;
+
+ /* Apply class-code bitmask, before checking each class-code byte */
+ for (i = 1; i <= 3; i++) {
+ byte_shift = 8 * (3 - i);
+ msk = (id->cls_msk >> byte_shift) & 0xFF;
+ if (!msk)
+ continue;
+
+ sprintf(buf, "%02x", (id->cls >> byte_shift) & msk);
+ if (strncmp(buf, &hwid->id[(i - 1) * 2], 2))
+ return false;
+ }
+ return true;
+}
+
+static const struct acpi_device_id *__acpi_match_device(
+ struct acpi_device *device,
+ const struct acpi_device_id *ids,
+ const struct of_device_id *of_ids)
+{
+ const struct acpi_device_id *id;
+ struct acpi_hardware_id *hwid;
+
+ /*
+ * If the device is not present, it is unnecessary to load device
+ * driver for it.
+ */
+ if (!device || !device->status.present)
+ return NULL;
+
+ list_for_each_entry(hwid, &device->pnp.ids, list) {
+ /* First, check the ACPI/PNP IDs provided by the caller. */
+ for (id = ids; id->id[0] || id->cls; id++) {
+ if (id->id[0] && !strcmp((char *) id->id, hwid->id))
+ return id;
+ else if (id->cls && __acpi_match_device_cls(id, hwid))
+ return id;
+ }
+
+ /*
+ * Next, check ACPI_DT_NAMESPACE_HID and try to match the
+ * "compatible" property if found.
+ *
+ * The id returned by the below is not valid, but the only
+ * caller passing non-NULL of_ids here is only interested in
+ * whether or not the return value is NULL.
+ */
+ if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)
+ && acpi_of_match_device(device, of_ids))
+ return id;
+ }
+ return NULL;
+}
+
+/**
+ * acpi_match_device - Match a struct device against a given list of ACPI IDs
+ * @ids: Array of struct acpi_device_id object to match against.
+ * @dev: The device structure to match.
+ *
+ * Check if @dev has a valid ACPI handle and if there is a struct acpi_device
+ * object for that handle and use that object to match against a given list of
+ * device IDs.
+ *
+ * Return a pointer to the first matching ID on success or %NULL on failure.
+ */
+const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+ const struct device *dev)
+{
+ return __acpi_match_device(acpi_companion_match(dev), ids, NULL);
+}
+EXPORT_SYMBOL_GPL(acpi_match_device);
+
+int acpi_match_device_ids(struct acpi_device *device,
+ const struct acpi_device_id *ids)
+{
+ return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT;
+}
+EXPORT_SYMBOL(acpi_match_device_ids);
+
+bool acpi_driver_match_device(struct device *dev,
+ const struct device_driver *drv)
+{
+ if (!drv->acpi_match_table)
+ return acpi_of_match_device(ACPI_COMPANION(dev),
+ drv->of_match_table);
+
+ return !!__acpi_match_device(acpi_companion_match(dev),
+ drv->acpi_match_table, drv->of_match_table);
+}
+EXPORT_SYMBOL_GPL(acpi_driver_match_device);
+
+/* --------------------------------------------------------------------------
+ ACPI Driver Management
+ -------------------------------------------------------------------------- */
+
+/**
+ * acpi_bus_register_driver - register a driver with the ACPI bus
+ * @driver: driver being registered
+ *
+ * Registers a driver with the ACPI bus. Searches the namespace for all
+ * devices that match the driver's criteria and binds. Returns zero for
+ * success or a negative error status for failure.
+ */
+int acpi_bus_register_driver(struct acpi_driver *driver)
+{
+ int ret;
+
+ if (acpi_disabled)
+ return -ENODEV;
+ driver->drv.name = driver->name;
+ driver->drv.bus = &acpi_bus_type;
+ driver->drv.owner = driver->owner;
+
+ ret = driver_register(&driver->drv);
+ return ret;
+}
+
+EXPORT_SYMBOL(acpi_bus_register_driver);
+
+/**
+ * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus
+ * @driver: driver to unregister
+ *
+ * Unregisters a driver with the ACPI bus. Searches the namespace for all
+ * devices that match the driver's criteria and unbinds.
+ */
+void acpi_bus_unregister_driver(struct acpi_driver *driver)
+{
+ driver_unregister(&driver->drv);
+}
+
+EXPORT_SYMBOL(acpi_bus_unregister_driver);
+
+/* --------------------------------------------------------------------------
+ ACPI Bus operations
+ -------------------------------------------------------------------------- */
+
+static int acpi_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = to_acpi_driver(drv);
+
+ return acpi_dev->flags.match_driver
+ && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+}
+
+static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ return __acpi_device_uevent_modalias(to_acpi_device(dev), env);
+}
+
+static int acpi_device_probe(struct device *dev)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
+ int ret;
+
+ if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
+ return -EINVAL;
+
+ if (!acpi_drv->ops.add)
+ return -ENOSYS;
+
+ ret = acpi_drv->ops.add(acpi_dev);
+ if (ret)
+ return ret;
+
+ acpi_dev->driver = acpi_drv;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Driver [%s] successfully bound to device [%s]\n",
+ acpi_drv->name, acpi_dev->pnp.bus_id));
+
+ if (acpi_drv->ops.notify) {
+ ret = acpi_device_install_notify_handler(acpi_dev);
+ if (ret) {
+ if (acpi_drv->ops.remove)
+ acpi_drv->ops.remove(acpi_dev);
+
+ acpi_dev->driver = NULL;
+ acpi_dev->driver_data = NULL;
+ return ret;
+ }
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
+ acpi_drv->name, acpi_dev->pnp.bus_id));
+ get_device(dev);
+ return 0;
+}
+
+static int acpi_device_remove(struct device * dev)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_driver *acpi_drv = acpi_dev->driver;
+
+ if (acpi_drv) {
+ if (acpi_drv->ops.notify)
+ acpi_device_remove_notify_handler(acpi_dev);
+ if (acpi_drv->ops.remove)
+ acpi_drv->ops.remove(acpi_dev);
+ }
+ acpi_dev->driver = NULL;
+ acpi_dev->driver_data = NULL;
+
+ put_device(dev);
+ return 0;
+}
+
+struct bus_type acpi_bus_type = {
+ .name = "acpi",
+ .match = acpi_bus_match,
+ .probe = acpi_device_probe,
+ .remove = acpi_device_remove,
+ .uevent = acpi_device_uevent,
+};
+
/* --------------------------------------------------------------------------
Initialization/Cleanup
-------------------------------------------------------------------------- */
@@ -661,7 +1068,9 @@
*/
acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);
- return 0;
+ result = bus_register(&acpi_bus_type);
+ if (!result)
+ return 0;
/* Mimic structured exception handling */
error1:
diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c
new file mode 100644
index 0000000..4ab4582
--- /dev/null
+++ b/drivers/acpi/device_sysfs.c
@@ -0,0 +1,521 @@
+/*
+ * drivers/acpi/device_sysfs.c - ACPI device sysfs attributes and modalias.
+ *
+ * Copyright (C) 2015, Intel Corp.
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/nls.h>
+
+#include "internal.h"
+
+/**
+ * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
+ * @acpi_dev: ACPI device object.
+ * @modalias: Buffer to print into.
+ * @size: Size of the buffer.
+ *
+ * Creates hid/cid(s) string needed for modalias and uevent
+ * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
+ * char *modalias: "acpi:IBM0001:ACPI0001"
+ * Return: 0: no _HID and no _CID
+ * -EINVAL: output error
+ * -ENOMEM: output is truncated
+*/
+static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
+ int size)
+{
+ int len;
+ int count;
+ struct acpi_hardware_id *id;
+
+ /*
+ * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
+ * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
+ * device's list.
+ */
+ count = 0;
+ list_for_each_entry(id, &acpi_dev->pnp.ids, list)
+ if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
+ count++;
+
+ if (!count)
+ return 0;
+
+ len = snprintf(modalias, size, "acpi:");
+ if (len <= 0)
+ return len;
+
+ size -= len;
+
+ list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
+ if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
+ continue;
+
+ count = snprintf(&modalias[len], size, "%s:", id->id);
+ if (count < 0)
+ return -EINVAL;
+
+ if (count >= size)
+ return -ENOMEM;
+
+ len += count;
+ size -= count;
+ }
+ modalias[len] = '\0';
+ return len;
+}
+
+/**
+ * create_of_modalias - Creates DT compatible string for modalias and uevent
+ * @acpi_dev: ACPI device object.
+ * @modalias: Buffer to print into.
+ * @size: Size of the buffer.
+ *
+ * Expose DT compatible modalias as of:NnameTCcompatible. This function should
+ * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
+ * ACPI/PNP IDs.
+ */
+static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
+ int size)
+{
+ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+ const union acpi_object *of_compatible, *obj;
+ int len, count;
+ int i, nval;
+ char *c;
+
+ acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
+ /* DT strings are all in lower case */
+ for (c = buf.pointer; *c != '\0'; c++)
+ *c = tolower(*c);
+
+ len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
+ ACPI_FREE(buf.pointer);
+
+ if (len <= 0)
+ return len;
+
+ of_compatible = acpi_dev->data.of_compatible;
+ if (of_compatible->type == ACPI_TYPE_PACKAGE) {
+ nval = of_compatible->package.count;
+ obj = of_compatible->package.elements;
+ } else { /* Must be ACPI_TYPE_STRING. */
+ nval = 1;
+ obj = of_compatible;
+ }
+ for (i = 0; i < nval; i++, obj++) {
+ count = snprintf(&modalias[len], size, "C%s",
+ obj->string.pointer);
+ if (count < 0)
+ return -EINVAL;
+
+ if (count >= size)
+ return -ENOMEM;
+
+ len += count;
+ size -= count;
+ }
+ modalias[len] = '\0';
+ return len;
+}
+
+int __acpi_device_uevent_modalias(struct acpi_device *adev,
+ struct kobj_uevent_env *env)
+{
+ int len;
+
+ if (!adev)
+ return -ENODEV;
+
+ if (list_empty(&adev->pnp.ids))
+ return 0;
+
+ if (add_uevent_var(env, "MODALIAS="))
+ return -ENOMEM;
+
+ len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
+ sizeof(env->buf) - env->buflen);
+ if (len < 0)
+ return len;
+
+ env->buflen += len;
+ if (!adev->data.of_compatible)
+ return 0;
+
+ if (len > 0 && add_uevent_var(env, "MODALIAS="))
+ return -ENOMEM;
+
+ len = create_of_modalias(adev, &env->buf[env->buflen - 1],
+ sizeof(env->buf) - env->buflen);
+ if (len < 0)
+ return len;
+
+ env->buflen += len;
+
+ return 0;
+}
+
+/**
+ * acpi_device_uevent_modalias - uevent modalias for ACPI-enumerated devices.
+ *
+ * Create the uevent modalias field for ACPI-enumerated devices.
+ *
+ * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
+ * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
+ */
+int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
+{
+ return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
+}
+EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
+
+static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
+{
+ int len, count;
+
+ if (!adev)
+ return -ENODEV;
+
+ if (list_empty(&adev->pnp.ids))
+ return 0;
+
+ len = create_pnp_modalias(adev, buf, size - 1);
+ if (len < 0) {
+ return len;
+ } else if (len > 0) {
+ buf[len++] = '\n';
+ size -= len;
+ }
+ if (!adev->data.of_compatible)
+ return len;
+
+ count = create_of_modalias(adev, buf + len, size - 1);
+ if (count < 0) {
+ return count;
+ } else if (count > 0) {
+ len += count;
+ buf[len++] = '\n';
+ }
+
+ return len;
+}
+
+/**
+ * acpi_device_modalias - modalias sysfs attribute for ACPI-enumerated devices.
+ *
+ * Create the modalias sysfs attribute for ACPI-enumerated devices.
+ *
+ * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
+ * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
+ */
+int acpi_device_modalias(struct device *dev, char *buf, int size)
+{
+ return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
+}
+EXPORT_SYMBOL_GPL(acpi_device_modalias);
+
+static ssize_t
+acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
+}
+static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
+
+static ssize_t real_power_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct acpi_device *adev = to_acpi_device(dev);
+ int state;
+ int ret;
+
+ ret = acpi_device_get_power(adev, &state);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%s\n", acpi_power_state_string(state));
+}
+
+static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL);
+
+static ssize_t power_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct acpi_device *adev = to_acpi_device(dev);
+
+ return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
+}
+
+static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);
+
+static ssize_t
+acpi_eject_store(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct acpi_device *acpi_device = to_acpi_device(d);
+ acpi_object_type not_used;
+ acpi_status status;
+
+ if (!count || buf[0] != '1')
+ return -EINVAL;
+
+ if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
+ && !acpi_device->driver)
+ return -ENODEV;
+
+ status = acpi_get_type(acpi_device->handle, ¬_used);
+ if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
+ return -ENODEV;
+
+ get_device(&acpi_device->dev);
+ status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);
+ if (ACPI_SUCCESS(status))
+ return count;
+
+ put_device(&acpi_device->dev);
+ acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
+ ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
+ return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
+}
+
+static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
+
+static ssize_t
+acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+ return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
+}
+static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
+
+static ssize_t acpi_device_uid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+ return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
+}
+static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
+
+static ssize_t acpi_device_adr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+ return sprintf(buf, "0x%08x\n",
+ (unsigned int)(acpi_dev->pnp.bus_address));
+}
+static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
+
+static ssize_t
+acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
+ int result;
+
+ result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
+ if (result)
+ goto end;
+
+ result = sprintf(buf, "%s\n", (char*)path.pointer);
+ kfree(path.pointer);
+end:
+ return result;
+}
+static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
+
+/* sysfs file that shows description text from the ACPI _STR method */
+static ssize_t description_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ int result;
+
+ if (acpi_dev->pnp.str_obj == NULL)
+ return 0;
+
+ /*
+ * The _STR object contains a Unicode identifier for a device.
+ * We need to convert to utf-8 so it can be displayed.
+ */
+ result = utf16s_to_utf8s(
+ (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
+ acpi_dev->pnp.str_obj->buffer.length,
+ UTF16_LITTLE_ENDIAN, buf,
+ PAGE_SIZE);
+
+ buf[result++] = '\n';
+
+ return result;
+}
+static DEVICE_ATTR(description, 0444, description_show, NULL);
+
+static ssize_t
+acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ acpi_status status;
+ unsigned long long sun;
+
+ status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return sprintf(buf, "%llu\n", sun);
+}
+static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
+
+static ssize_t status_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ acpi_status status;
+ unsigned long long sta;
+
+ status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return sprintf(buf, "%llu\n", sta);
+}
+static DEVICE_ATTR_RO(status);
+
+/**
+ * acpi_device_setup_files - Create sysfs attributes of an ACPI device.
+ * @dev: ACPI device object.
+ */
+int acpi_device_setup_files(struct acpi_device *dev)
+{
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ acpi_status status;
+ int result = 0;
+
+ /*
+ * Devices gotten from FADT don't have a "path" attribute
+ */
+ if (dev->handle) {
+ result = device_create_file(&dev->dev, &dev_attr_path);
+ if (result)
+ goto end;
+ }
+
+ if (!list_empty(&dev->pnp.ids)) {
+ result = device_create_file(&dev->dev, &dev_attr_hid);
+ if (result)
+ goto end;
+
+ result = device_create_file(&dev->dev, &dev_attr_modalias);
+ if (result)
+ goto end;
+ }
+
+ /*
+ * If device has _STR, 'description' file is created
+ */
+ if (acpi_has_method(dev->handle, "_STR")) {
+ status = acpi_evaluate_object(dev->handle, "_STR",
+ NULL, &buffer);
+ if (ACPI_FAILURE(status))
+ buffer.pointer = NULL;
+ dev->pnp.str_obj = buffer.pointer;
+ result = device_create_file(&dev->dev, &dev_attr_description);
+ if (result)
+ goto end;
+ }
+
+ if (dev->pnp.type.bus_address)
+ result = device_create_file(&dev->dev, &dev_attr_adr);
+ if (dev->pnp.unique_id)
+ result = device_create_file(&dev->dev, &dev_attr_uid);
+
+ if (acpi_has_method(dev->handle, "_SUN")) {
+ result = device_create_file(&dev->dev, &dev_attr_sun);
+ if (result)
+ goto end;
+ }
+
+ if (acpi_has_method(dev->handle, "_STA")) {
+ result = device_create_file(&dev->dev, &dev_attr_status);
+ if (result)
+ goto end;
+ }
+
+ /*
+ * If device has _EJ0, 'eject' file is created that is used to trigger
+ * hot-removal function from userland.
+ */
+ if (acpi_has_method(dev->handle, "_EJ0")) {
+ result = device_create_file(&dev->dev, &dev_attr_eject);
+ if (result)
+ return result;
+ }
+
+ if (dev->flags.power_manageable) {
+ result = device_create_file(&dev->dev, &dev_attr_power_state);
+ if (result)
+ return result;
+
+ if (dev->power.flags.power_resources)
+ result = device_create_file(&dev->dev,
+ &dev_attr_real_power_state);
+ }
+
+end:
+ return result;
+}
+
+/**
+ * acpi_device_remove_files - Remove sysfs attributes of an ACPI device.
+ * @dev: ACPI device object.
+ */
+void acpi_device_remove_files(struct acpi_device *dev)
+{
+ if (dev->flags.power_manageable) {
+ device_remove_file(&dev->dev, &dev_attr_power_state);
+ if (dev->power.flags.power_resources)
+ device_remove_file(&dev->dev,
+ &dev_attr_real_power_state);
+ }
+
+ /*
+ * If device has _STR, remove 'description' file
+ */
+ if (acpi_has_method(dev->handle, "_STR")) {
+ kfree(dev->pnp.str_obj);
+ device_remove_file(&dev->dev, &dev_attr_description);
+ }
+ /*
+ * If device has _EJ0, remove 'eject' file.
+ */
+ if (acpi_has_method(dev->handle, "_EJ0"))
+ device_remove_file(&dev->dev, &dev_attr_eject);
+
+ if (acpi_has_method(dev->handle, "_SUN"))
+ device_remove_file(&dev->dev, &dev_attr_sun);
+
+ if (dev->pnp.unique_id)
+ device_remove_file(&dev->dev, &dev_attr_uid);
+ if (dev->pnp.type.bus_address)
+ device_remove_file(&dev->dev, &dev_attr_adr);
+ device_remove_file(&dev->dev, &dev_attr_modalias);
+ device_remove_file(&dev->dev, &dev_attr_hid);
+ if (acpi_has_method(dev->handle, "_STA"))
+ device_remove_file(&dev->dev, &dev_attr_status);
+ if (dev->handle)
+ device_remove_file(&dev->dev, &dev_attr_path);
+}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index f6aefe9..df7f7af 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -93,6 +93,8 @@
void (*release)(struct device *));
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
int type, unsigned long long sta);
+int acpi_device_setup_files(struct acpi_device *dev);
+void acpi_device_remove_files(struct acpi_device *dev);
void acpi_device_add_finalize(struct acpi_device *device);
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
bool acpi_device_is_present(struct acpi_device *adev);
@@ -101,6 +103,13 @@
const struct device *dev);
/* --------------------------------------------------------------------------
+ Device Matching and Notification
+ -------------------------------------------------------------------------- */
+struct acpi_device *acpi_companion_match(const struct device *dev);
+int __acpi_device_uevent_modalias(struct acpi_device *adev,
+ struct kobj_uevent_env *env);
+
+/* --------------------------------------------------------------------------
Power Resource
-------------------------------------------------------------------------- */
int acpi_power_init(void);
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 8244f01..f1c966e 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -193,6 +193,7 @@
u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
bool wp = addr->info.mem.write_protect;
u64 len = attr->address_length;
+ u64 start, end, offset = 0;
struct resource *res = &win->res;
/*
@@ -204,9 +205,6 @@
pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",
addr->min_address_fixed, addr->max_address_fixed, len);
- res->start = attr->minimum;
- res->end = attr->maximum;
-
/*
* For bridges that translate addresses across the bridge,
* translation_offset is the offset that must be added to the
@@ -214,12 +212,22 @@
* primary side. Non-bridge devices must list 0 for all Address
* Translation offset bits.
*/
- if (addr->producer_consumer == ACPI_PRODUCER) {
- res->start += attr->translation_offset;
- res->end += attr->translation_offset;
- } else if (attr->translation_offset) {
+ if (addr->producer_consumer == ACPI_PRODUCER)
+ offset = attr->translation_offset;
+ else if (attr->translation_offset)
pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
attr->translation_offset);
+ start = attr->minimum + offset;
+ end = attr->maximum + offset;
+
+ win->offset = offset;
+ res->start = start;
+ res->end = end;
+ if (sizeof(resource_size_t) < sizeof(u64) &&
+ (offset != win->offset || start != res->start || end != res->end)) {
+ pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",
+ attr->minimum, attr->maximum);
+ return false;
}
switch (addr->resource_type) {
@@ -236,8 +244,6 @@
return false;
}
- win->offset = attr->translation_offset;
-
if (addr->producer_consumer == ACPI_PRODUCER)
res->flags |= IORESOURCE_WINDOW;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 89ff6d2..01136b8 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -115,278 +115,6 @@
return 0;
}
-/**
- * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
- * @acpi_dev: ACPI device object.
- * @modalias: Buffer to print into.
- * @size: Size of the buffer.
- *
- * Creates hid/cid(s) string needed for modalias and uevent
- * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
- * char *modalias: "acpi:IBM0001:ACPI0001"
- * Return: 0: no _HID and no _CID
- * -EINVAL: output error
- * -ENOMEM: output is truncated
-*/
-static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
- int size)
-{
- int len;
- int count;
- struct acpi_hardware_id *id;
-
- /*
- * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
- * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
- * device's list.
- */
- count = 0;
- list_for_each_entry(id, &acpi_dev->pnp.ids, list)
- if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
- count++;
-
- if (!count)
- return 0;
-
- len = snprintf(modalias, size, "acpi:");
- if (len <= 0)
- return len;
-
- size -= len;
-
- list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
- if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
- continue;
-
- count = snprintf(&modalias[len], size, "%s:", id->id);
- if (count < 0)
- return -EINVAL;
-
- if (count >= size)
- return -ENOMEM;
-
- len += count;
- size -= count;
- }
- modalias[len] = '\0';
- return len;
-}
-
-/**
- * create_of_modalias - Creates DT compatible string for modalias and uevent
- * @acpi_dev: ACPI device object.
- * @modalias: Buffer to print into.
- * @size: Size of the buffer.
- *
- * Expose DT compatible modalias as of:NnameTCcompatible. This function should
- * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
- * ACPI/PNP IDs.
- */
-static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
- int size)
-{
- struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
- const union acpi_object *of_compatible, *obj;
- int len, count;
- int i, nval;
- char *c;
-
- acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
- /* DT strings are all in lower case */
- for (c = buf.pointer; *c != '\0'; c++)
- *c = tolower(*c);
-
- len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
- ACPI_FREE(buf.pointer);
-
- if (len <= 0)
- return len;
-
- of_compatible = acpi_dev->data.of_compatible;
- if (of_compatible->type == ACPI_TYPE_PACKAGE) {
- nval = of_compatible->package.count;
- obj = of_compatible->package.elements;
- } else { /* Must be ACPI_TYPE_STRING. */
- nval = 1;
- obj = of_compatible;
- }
- for (i = 0; i < nval; i++, obj++) {
- count = snprintf(&modalias[len], size, "C%s",
- obj->string.pointer);
- if (count < 0)
- return -EINVAL;
-
- if (count >= size)
- return -ENOMEM;
-
- len += count;
- size -= count;
- }
- modalias[len] = '\0';
- return len;
-}
-
-/**
- * acpi_device_is_first_physical_node - Is given dev first physical node
- * @adev: ACPI companion device
- * @dev: Physical device to check
- *
- * Function checks if given @dev is the first physical devices attached to
- * the ACPI companion device. This distinction is needed in some cases
- * where the same companion device is shared between many physical devices.
- *
- * Note that the caller have to provide valid @adev pointer.
- */
-bool acpi_device_is_first_physical_node(struct acpi_device *adev,
- const struct device *dev)
-{
- bool ret = false;
-
- mutex_lock(&adev->physical_node_lock);
- if (!list_empty(&adev->physical_node_list)) {
- const struct acpi_device_physical_node *node;
-
- node = list_first_entry(&adev->physical_node_list,
- struct acpi_device_physical_node, node);
- ret = node->dev == dev;
- }
- mutex_unlock(&adev->physical_node_lock);
-
- return ret;
-}
-
-/*
- * acpi_companion_match() - Can we match via ACPI companion device
- * @dev: Device in question
- *
- * Check if the given device has an ACPI companion and if that companion has
- * a valid list of PNP IDs, and if the device is the first (primary) physical
- * device associated with it. Return the companion pointer if that's the case
- * or NULL otherwise.
- *
- * If multiple physical devices are attached to a single ACPI companion, we need
- * to be careful. The usage scenario for this kind of relationship is that all
- * of the physical devices in question use resources provided by the ACPI
- * companion. A typical case is an MFD device where all the sub-devices share
- * the parent's ACPI companion. In such cases we can only allow the primary
- * (first) physical device to be matched with the help of the companion's PNP
- * IDs.
- *
- * Additional physical devices sharing the ACPI companion can still use
- * resources available from it but they will be matched normally using functions
- * provided by their bus types (and analogously for their modalias).
- */
-static struct acpi_device *acpi_companion_match(const struct device *dev)
-{
- struct acpi_device *adev;
-
- adev = ACPI_COMPANION(dev);
- if (!adev)
- return NULL;
-
- if (list_empty(&adev->pnp.ids))
- return NULL;
-
- return acpi_device_is_first_physical_node(adev, dev) ? adev : NULL;
-}
-
-static int __acpi_device_uevent_modalias(struct acpi_device *adev,
- struct kobj_uevent_env *env)
-{
- int len;
-
- if (!adev)
- return -ENODEV;
-
- if (list_empty(&adev->pnp.ids))
- return 0;
-
- if (add_uevent_var(env, "MODALIAS="))
- return -ENOMEM;
-
- len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
- sizeof(env->buf) - env->buflen);
- if (len < 0)
- return len;
-
- env->buflen += len;
- if (!adev->data.of_compatible)
- return 0;
-
- if (len > 0 && add_uevent_var(env, "MODALIAS="))
- return -ENOMEM;
-
- len = create_of_modalias(adev, &env->buf[env->buflen - 1],
- sizeof(env->buf) - env->buflen);
- if (len < 0)
- return len;
-
- env->buflen += len;
-
- return 0;
-}
-
-/*
- * Creates uevent modalias field for ACPI enumerated devices.
- * Because the other buses does not support ACPI HIDs & CIDs.
- * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
- * "acpi:IBM0001:ACPI0001"
- */
-int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
-{
- return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
-}
-EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
-
-static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
-{
- int len, count;
-
- if (!adev)
- return -ENODEV;
-
- if (list_empty(&adev->pnp.ids))
- return 0;
-
- len = create_pnp_modalias(adev, buf, size - 1);
- if (len < 0) {
- return len;
- } else if (len > 0) {
- buf[len++] = '\n';
- size -= len;
- }
- if (!adev->data.of_compatible)
- return len;
-
- count = create_of_modalias(adev, buf + len, size - 1);
- if (count < 0) {
- return count;
- } else if (count > 0) {
- len += count;
- buf[len++] = '\n';
- }
-
- return len;
-}
-
-/*
- * Creates modalias sysfs attribute for ACPI enumerated devices.
- * Because the other buses does not support ACPI HIDs & CIDs.
- * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
- * "acpi:IBM0001:ACPI0001"
- */
-int acpi_device_modalias(struct device *dev, char *buf, int size)
-{
- return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
-}
-EXPORT_SYMBOL_GPL(acpi_device_modalias);
-
-static ssize_t
-acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
- return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
-}
-static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
-
bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
{
struct acpi_device_physical_node *pn;
@@ -715,423 +443,6 @@
unlock_device_hotplug();
}
-static ssize_t real_power_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_device *adev = to_acpi_device(dev);
- int state;
- int ret;
-
- ret = acpi_device_get_power(adev, &state);
- if (ret)
- return ret;
-
- return sprintf(buf, "%s\n", acpi_power_state_string(state));
-}
-
-static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL);
-
-static ssize_t power_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_device *adev = to_acpi_device(dev);
-
- return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
-}
-
-static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);
-
-static ssize_t
-acpi_eject_store(struct device *d, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct acpi_device *acpi_device = to_acpi_device(d);
- acpi_object_type not_used;
- acpi_status status;
-
- if (!count || buf[0] != '1')
- return -EINVAL;
-
- if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
- && !acpi_device->driver)
- return -ENODEV;
-
- status = acpi_get_type(acpi_device->handle, ¬_used);
- if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
- return -ENODEV;
-
- get_device(&acpi_device->dev);
- status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);
- if (ACPI_SUCCESS(status))
- return count;
-
- put_device(&acpi_device->dev);
- acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
- ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
- return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
-}
-
-static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
-
-static ssize_t
-acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
- struct acpi_device *acpi_dev = to_acpi_device(dev);
-
- return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
-}
-static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
-
-static ssize_t acpi_device_uid_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
-
- return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
-}
-static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
-
-static ssize_t acpi_device_adr_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
-
- return sprintf(buf, "0x%08x\n",
- (unsigned int)(acpi_dev->pnp.bus_address));
-}
-static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
-
-static ssize_t
-acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
- int result;
-
- result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
- if (result)
- goto end;
-
- result = sprintf(buf, "%s\n", (char*)path.pointer);
- kfree(path.pointer);
-end:
- return result;
-}
-static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
-
-/* sysfs file that shows description text from the ACPI _STR method */
-static ssize_t description_show(struct device *dev,
- struct device_attribute *attr,
- char *buf) {
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- int result;
-
- if (acpi_dev->pnp.str_obj == NULL)
- return 0;
-
- /*
- * The _STR object contains a Unicode identifier for a device.
- * We need to convert to utf-8 so it can be displayed.
- */
- result = utf16s_to_utf8s(
- (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
- acpi_dev->pnp.str_obj->buffer.length,
- UTF16_LITTLE_ENDIAN, buf,
- PAGE_SIZE);
-
- buf[result++] = '\n';
-
- return result;
-}
-static DEVICE_ATTR(description, 0444, description_show, NULL);
-
-static ssize_t
-acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
- char *buf) {
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- acpi_status status;
- unsigned long long sun;
-
- status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- return sprintf(buf, "%llu\n", sun);
-}
-static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
-
-static ssize_t status_show(struct device *dev, struct device_attribute *attr,
- char *buf) {
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- acpi_status status;
- unsigned long long sta;
-
- status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- return sprintf(buf, "%llu\n", sta);
-}
-static DEVICE_ATTR_RO(status);
-
-static int acpi_device_setup_files(struct acpi_device *dev)
-{
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- acpi_status status;
- int result = 0;
-
- /*
- * Devices gotten from FADT don't have a "path" attribute
- */
- if (dev->handle) {
- result = device_create_file(&dev->dev, &dev_attr_path);
- if (result)
- goto end;
- }
-
- if (!list_empty(&dev->pnp.ids)) {
- result = device_create_file(&dev->dev, &dev_attr_hid);
- if (result)
- goto end;
-
- result = device_create_file(&dev->dev, &dev_attr_modalias);
- if (result)
- goto end;
- }
-
- /*
- * If device has _STR, 'description' file is created
- */
- if (acpi_has_method(dev->handle, "_STR")) {
- status = acpi_evaluate_object(dev->handle, "_STR",
- NULL, &buffer);
- if (ACPI_FAILURE(status))
- buffer.pointer = NULL;
- dev->pnp.str_obj = buffer.pointer;
- result = device_create_file(&dev->dev, &dev_attr_description);
- if (result)
- goto end;
- }
-
- if (dev->pnp.type.bus_address)
- result = device_create_file(&dev->dev, &dev_attr_adr);
- if (dev->pnp.unique_id)
- result = device_create_file(&dev->dev, &dev_attr_uid);
-
- if (acpi_has_method(dev->handle, "_SUN")) {
- result = device_create_file(&dev->dev, &dev_attr_sun);
- if (result)
- goto end;
- }
-
- if (acpi_has_method(dev->handle, "_STA")) {
- result = device_create_file(&dev->dev, &dev_attr_status);
- if (result)
- goto end;
- }
-
- /*
- * If device has _EJ0, 'eject' file is created that is used to trigger
- * hot-removal function from userland.
- */
- if (acpi_has_method(dev->handle, "_EJ0")) {
- result = device_create_file(&dev->dev, &dev_attr_eject);
- if (result)
- return result;
- }
-
- if (dev->flags.power_manageable) {
- result = device_create_file(&dev->dev, &dev_attr_power_state);
- if (result)
- return result;
-
- if (dev->power.flags.power_resources)
- result = device_create_file(&dev->dev,
- &dev_attr_real_power_state);
- }
-
-end:
- return result;
-}
-
-static void acpi_device_remove_files(struct acpi_device *dev)
-{
- if (dev->flags.power_manageable) {
- device_remove_file(&dev->dev, &dev_attr_power_state);
- if (dev->power.flags.power_resources)
- device_remove_file(&dev->dev,
- &dev_attr_real_power_state);
- }
-
- /*
- * If device has _STR, remove 'description' file
- */
- if (acpi_has_method(dev->handle, "_STR")) {
- kfree(dev->pnp.str_obj);
- device_remove_file(&dev->dev, &dev_attr_description);
- }
- /*
- * If device has _EJ0, remove 'eject' file.
- */
- if (acpi_has_method(dev->handle, "_EJ0"))
- device_remove_file(&dev->dev, &dev_attr_eject);
-
- if (acpi_has_method(dev->handle, "_SUN"))
- device_remove_file(&dev->dev, &dev_attr_sun);
-
- if (dev->pnp.unique_id)
- device_remove_file(&dev->dev, &dev_attr_uid);
- if (dev->pnp.type.bus_address)
- device_remove_file(&dev->dev, &dev_attr_adr);
- device_remove_file(&dev->dev, &dev_attr_modalias);
- device_remove_file(&dev->dev, &dev_attr_hid);
- if (acpi_has_method(dev->handle, "_STA"))
- device_remove_file(&dev->dev, &dev_attr_status);
- if (dev->handle)
- device_remove_file(&dev->dev, &dev_attr_path);
-}
-/* --------------------------------------------------------------------------
- ACPI Bus operations
- -------------------------------------------------------------------------- */
-
-/**
- * acpi_of_match_device - Match device object using the "compatible" property.
- * @adev: ACPI device object to match.
- * @of_match_table: List of device IDs to match against.
- *
- * If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of
- * identifiers and a _DSD object with the "compatible" property, use that
- * property to match against the given list of identifiers.
- */
-static bool acpi_of_match_device(struct acpi_device *adev,
- const struct of_device_id *of_match_table)
-{
- const union acpi_object *of_compatible, *obj;
- int i, nval;
-
- if (!adev)
- return false;
-
- of_compatible = adev->data.of_compatible;
- if (!of_match_table || !of_compatible)
- return false;
-
- if (of_compatible->type == ACPI_TYPE_PACKAGE) {
- nval = of_compatible->package.count;
- obj = of_compatible->package.elements;
- } else { /* Must be ACPI_TYPE_STRING. */
- nval = 1;
- obj = of_compatible;
- }
- /* Now we can look for the driver DT compatible strings */
- for (i = 0; i < nval; i++, obj++) {
- const struct of_device_id *id;
-
- for (id = of_match_table; id->compatible[0]; id++)
- if (!strcasecmp(obj->string.pointer, id->compatible))
- return true;
- }
-
- return false;
-}
-
-static bool __acpi_match_device_cls(const struct acpi_device_id *id,
- struct acpi_hardware_id *hwid)
-{
- int i, msk, byte_shift;
- char buf[3];
-
- if (!id->cls)
- return false;
-
- /* Apply class-code bitmask, before checking each class-code byte */
- for (i = 1; i <= 3; i++) {
- byte_shift = 8 * (3 - i);
- msk = (id->cls_msk >> byte_shift) & 0xFF;
- if (!msk)
- continue;
-
- sprintf(buf, "%02x", (id->cls >> byte_shift) & msk);
- if (strncmp(buf, &hwid->id[(i - 1) * 2], 2))
- return false;
- }
- return true;
-}
-
-static const struct acpi_device_id *__acpi_match_device(
- struct acpi_device *device,
- const struct acpi_device_id *ids,
- const struct of_device_id *of_ids)
-{
- const struct acpi_device_id *id;
- struct acpi_hardware_id *hwid;
-
- /*
- * If the device is not present, it is unnecessary to load device
- * driver for it.
- */
- if (!device || !device->status.present)
- return NULL;
-
- list_for_each_entry(hwid, &device->pnp.ids, list) {
- /* First, check the ACPI/PNP IDs provided by the caller. */
- for (id = ids; id->id[0] || id->cls; id++) {
- if (id->id[0] && !strcmp((char *) id->id, hwid->id))
- return id;
- else if (id->cls && __acpi_match_device_cls(id, hwid))
- return id;
- }
-
- /*
- * Next, check ACPI_DT_NAMESPACE_HID and try to match the
- * "compatible" property if found.
- *
- * The id returned by the below is not valid, but the only
- * caller passing non-NULL of_ids here is only interested in
- * whether or not the return value is NULL.
- */
- if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)
- && acpi_of_match_device(device, of_ids))
- return id;
- }
- return NULL;
-}
-
-/**
- * acpi_match_device - Match a struct device against a given list of ACPI IDs
- * @ids: Array of struct acpi_device_id object to match against.
- * @dev: The device structure to match.
- *
- * Check if @dev has a valid ACPI handle and if there is a struct acpi_device
- * object for that handle and use that object to match against a given list of
- * device IDs.
- *
- * Return a pointer to the first matching ID on success or %NULL on failure.
- */
-const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
- const struct device *dev)
-{
- return __acpi_match_device(acpi_companion_match(dev), ids, NULL);
-}
-EXPORT_SYMBOL_GPL(acpi_match_device);
-
-int acpi_match_device_ids(struct acpi_device *device,
- const struct acpi_device_id *ids)
-{
- return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT;
-}
-EXPORT_SYMBOL(acpi_match_device_ids);
-
-bool acpi_driver_match_device(struct device *dev,
- const struct device_driver *drv)
-{
- if (!drv->acpi_match_table)
- return acpi_of_match_device(ACPI_COMPANION(dev),
- drv->of_match_table);
-
- return !!__acpi_match_device(acpi_companion_match(dev),
- drv->acpi_match_table, drv->of_match_table);
-}
-EXPORT_SYMBOL_GPL(acpi_driver_match_device);
-
static void acpi_free_power_resources_lists(struct acpi_device *device)
{
int i;
@@ -1158,144 +469,6 @@
kfree(acpi_dev);
}
-static int acpi_bus_match(struct device *dev, struct device_driver *drv)
-{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_driver *acpi_drv = to_acpi_driver(drv);
-
- return acpi_dev->flags.match_driver
- && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
-}
-
-static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- return __acpi_device_uevent_modalias(to_acpi_device(dev), env);
-}
-
-static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
-{
- struct acpi_device *device = data;
-
- device->driver->ops.notify(device, event);
-}
-
-static void acpi_device_notify_fixed(void *data)
-{
- struct acpi_device *device = data;
-
- /* Fixed hardware devices have no handles */
- acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
-}
-
-static u32 acpi_device_fixed_event(void *data)
-{
- acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
- return ACPI_INTERRUPT_HANDLED;
-}
-
-static int acpi_device_install_notify_handler(struct acpi_device *device)
-{
- acpi_status status;
-
- if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
- status =
- acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
- acpi_device_fixed_event,
- device);
- else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
- status =
- acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
- acpi_device_fixed_event,
- device);
- else
- status = acpi_install_notify_handler(device->handle,
- ACPI_DEVICE_NOTIFY,
- acpi_device_notify,
- device);
-
- if (ACPI_FAILURE(status))
- return -EINVAL;
- return 0;
-}
-
-static void acpi_device_remove_notify_handler(struct acpi_device *device)
-{
- if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
- acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
- acpi_device_fixed_event);
- else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
- acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
- acpi_device_fixed_event);
- else
- acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
- acpi_device_notify);
-}
-
-static int acpi_device_probe(struct device *dev)
-{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
- int ret;
-
- if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
- return -EINVAL;
-
- if (!acpi_drv->ops.add)
- return -ENOSYS;
-
- ret = acpi_drv->ops.add(acpi_dev);
- if (ret)
- return ret;
-
- acpi_dev->driver = acpi_drv;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Driver [%s] successfully bound to device [%s]\n",
- acpi_drv->name, acpi_dev->pnp.bus_id));
-
- if (acpi_drv->ops.notify) {
- ret = acpi_device_install_notify_handler(acpi_dev);
- if (ret) {
- if (acpi_drv->ops.remove)
- acpi_drv->ops.remove(acpi_dev);
-
- acpi_dev->driver = NULL;
- acpi_dev->driver_data = NULL;
- return ret;
- }
- }
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
- acpi_drv->name, acpi_dev->pnp.bus_id));
- get_device(dev);
- return 0;
-}
-
-static int acpi_device_remove(struct device * dev)
-{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_driver *acpi_drv = acpi_dev->driver;
-
- if (acpi_drv) {
- if (acpi_drv->ops.notify)
- acpi_device_remove_notify_handler(acpi_dev);
- if (acpi_drv->ops.remove)
- acpi_drv->ops.remove(acpi_dev);
- }
- acpi_dev->driver = NULL;
- acpi_dev->driver_data = NULL;
-
- put_device(dev);
- return 0;
-}
-
-struct bus_type acpi_bus_type = {
- .name = "acpi",
- .match = acpi_bus_match,
- .probe = acpi_device_probe,
- .remove = acpi_device_remove,
- .uevent = acpi_device_uevent,
-};
-
static void acpi_device_del(struct acpi_device *device)
{
mutex_lock(&acpi_device_lock);
@@ -1543,47 +716,6 @@
}
/* --------------------------------------------------------------------------
- Driver Management
- -------------------------------------------------------------------------- */
-/**
- * acpi_bus_register_driver - register a driver with the ACPI bus
- * @driver: driver being registered
- *
- * Registers a driver with the ACPI bus. Searches the namespace for all
- * devices that match the driver's criteria and binds. Returns zero for
- * success or a negative error status for failure.
- */
-int acpi_bus_register_driver(struct acpi_driver *driver)
-{
- int ret;
-
- if (acpi_disabled)
- return -ENODEV;
- driver->drv.name = driver->name;
- driver->drv.bus = &acpi_bus_type;
- driver->drv.owner = driver->owner;
-
- ret = driver_register(&driver->drv);
- return ret;
-}
-
-EXPORT_SYMBOL(acpi_bus_register_driver);
-
-/**
- * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus
- * @driver: driver to unregister
- *
- * Unregisters a driver with the ACPI bus. Searches the namespace for all
- * devices that match the driver's criteria and unbinds.
- */
-void acpi_bus_unregister_driver(struct acpi_driver *driver)
-{
- driver_unregister(&driver->drv);
-}
-
-EXPORT_SYMBOL(acpi_bus_unregister_driver);
-
-/* --------------------------------------------------------------------------
Device Enumeration
-------------------------------------------------------------------------- */
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
@@ -2758,12 +1890,6 @@
{
int result;
- result = bus_register(&acpi_bus_type);
- if (result) {
- /* We don't want to quit even if we failed to add suspend/resume */
- printk(KERN_ERR PREFIX "Could not register bus type\n");
- }
-
acpi_pci_root_init();
acpi_pci_link_init();
acpi_processor_init();
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index d1d6141..7920c27 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -2108,8 +2108,17 @@
goto out_free_disk;
add_disk(ns->disk);
- if (ns->ms)
- revalidate_disk(ns->disk);
+ if (ns->ms) {
+ struct block_device *bd = bdget_disk(ns->disk, 0);
+ if (!bd)
+ return;
+ if (blkdev_get(bd, FMODE_READ, NULL)) {
+ bdput(bd);
+ return;
+ }
+ blkdev_reread_part(bd);
+ blkdev_put(bd, FMODE_READ);
+ }
return;
out_free_disk:
kfree(disk);
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 283f00a..1082d4b 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -129,8 +129,9 @@
device_initialize(&chip->dev);
- chip->cdev.owner = chip->pdev->driver->owner;
cdev_init(&chip->cdev, &tpm_fops);
+ chip->cdev.owner = chip->pdev->driver->owner;
+ chip->cdev.kobj.parent = &chip->dev.kobj;
return chip;
}
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 44f9d20..1267322 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -233,6 +233,14 @@
return -ENODEV;
}
+ /* At least some versions of AMI BIOS have a bug that TPM2 table has
+ * zero address for the control area and therefore we must fail.
+ */
+ if (!buf->control_area_pa) {
+ dev_err(dev, "TPM2 ACPI table has a zero address for the control area\n");
+ return -EINVAL;
+ }
+
if (buf->hdr.length < sizeof(struct acpi_tpm2)) {
dev_err(dev, "TPM2 ACPI table has wrong size");
return -EINVAL;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b612411..26063af 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -169,6 +169,15 @@
}
EXPORT_SYMBOL_GPL(get_governor_parent_kobj);
+struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
+{
+ struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
+
+ return policy && !policy_is_inactive(policy) ?
+ policy->freq_table : NULL;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
+
static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
{
u64 idle_time;
@@ -1132,6 +1141,7 @@
down_write(&policy->rwsem);
policy->cpu = cpu;
+ policy->governor = NULL;
up_write(&policy->rwsem);
}
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index df14766..dfbbf981 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -297,15 +297,6 @@
}
EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
-struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
-
-struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
-{
- struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
- return policy ? policy->freq_table : NULL;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
-
MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION("CPUfreq frequency table helpers");
MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index e8e2775..48b7228 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -112,7 +112,12 @@
static void enter_freeze_proper(struct cpuidle_driver *drv,
struct cpuidle_device *dev, int index)
{
- tick_freeze();
+ /*
+ * trace_suspend_resume() called by tick_freeze() for the last CPU
+ * executing it contains RCU usage regarded as invalid in the idle
+ * context, so tell RCU about that.
+ */
+ RCU_NONIDLE(tick_freeze());
/*
* The state used here cannot be a "coupled" one, because the "coupled"
* cpuidle mechanism enables interrupts and doing that with timekeeping
@@ -122,7 +127,7 @@
WARN_ON(!irqs_disabled());
/*
* timekeeping_resume() that will be called by tick_unfreeze() for the
- * last CPU executing it calls functions containing RCU read-side
+ * first CPU executing it calls functions containing RCU read-side
* critical sections, so tell RCU about that.
*/
RCU_NONIDLE(tick_unfreeze());
diff --git a/drivers/crypto/nx/nx-aes-ccm.c b/drivers/crypto/nx/nx-aes-ccm.c
index 67f8081..e4311ce 100644
--- a/drivers/crypto/nx/nx-aes-ccm.c
+++ b/drivers/crypto/nx/nx-aes-ccm.c
@@ -494,8 +494,9 @@
static int ccm4309_aes_nx_encrypt(struct aead_request *req)
{
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ struct nx_gcm_rctx *rctx = aead_request_ctx(req);
struct blkcipher_desc desc;
- u8 *iv = nx_ctx->priv.ccm.iv;
+ u8 *iv = rctx->iv;
iv[0] = 3;
memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
@@ -525,8 +526,9 @@
static int ccm4309_aes_nx_decrypt(struct aead_request *req)
{
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ struct nx_gcm_rctx *rctx = aead_request_ctx(req);
struct blkcipher_desc desc;
- u8 *iv = nx_ctx->priv.ccm.iv;
+ u8 *iv = rctx->iv;
iv[0] = 3;
memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
diff --git a/drivers/crypto/nx/nx-aes-ctr.c b/drivers/crypto/nx/nx-aes-ctr.c
index 2617cd4..dd7e9f3 100644
--- a/drivers/crypto/nx/nx-aes-ctr.c
+++ b/drivers/crypto/nx/nx-aes-ctr.c
@@ -72,7 +72,7 @@
if (key_len < CTR_RFC3686_NONCE_SIZE)
return -EINVAL;
- memcpy(nx_ctx->priv.ctr.iv,
+ memcpy(nx_ctx->priv.ctr.nonce,
in_key + key_len - CTR_RFC3686_NONCE_SIZE,
CTR_RFC3686_NONCE_SIZE);
@@ -131,14 +131,15 @@
unsigned int nbytes)
{
struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
- u8 *iv = nx_ctx->priv.ctr.iv;
+ u8 iv[16];
+ memcpy(iv, nx_ctx->priv.ctr.nonce, CTR_RFC3686_IV_SIZE);
memcpy(iv + CTR_RFC3686_NONCE_SIZE,
desc->info, CTR_RFC3686_IV_SIZE);
iv[12] = iv[13] = iv[14] = 0;
iv[15] = 1;
- desc->info = nx_ctx->priv.ctr.iv;
+ desc->info = iv;
return ctr_aes_nx_crypt(desc, dst, src, nbytes);
}
diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c
index 08ac6d4..92c993f 100644
--- a/drivers/crypto/nx/nx-aes-gcm.c
+++ b/drivers/crypto/nx/nx-aes-gcm.c
@@ -317,6 +317,7 @@
static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
{
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ struct nx_gcm_rctx *rctx = aead_request_ctx(req);
struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
struct blkcipher_desc desc;
unsigned int nbytes = req->cryptlen;
@@ -326,7 +327,7 @@
spin_lock_irqsave(&nx_ctx->lock, irq_flags);
- desc.info = nx_ctx->priv.gcm.iv;
+ desc.info = rctx->iv;
/* initialize the counter */
*(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1;
@@ -424,8 +425,8 @@
static int gcm_aes_nx_encrypt(struct aead_request *req)
{
- struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
- char *iv = nx_ctx->priv.gcm.iv;
+ struct nx_gcm_rctx *rctx = aead_request_ctx(req);
+ char *iv = rctx->iv;
memcpy(iv, req->iv, 12);
@@ -434,8 +435,8 @@
static int gcm_aes_nx_decrypt(struct aead_request *req)
{
- struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
- char *iv = nx_ctx->priv.gcm.iv;
+ struct nx_gcm_rctx *rctx = aead_request_ctx(req);
+ char *iv = rctx->iv;
memcpy(iv, req->iv, 12);
@@ -445,7 +446,8 @@
static int gcm4106_aes_nx_encrypt(struct aead_request *req)
{
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
- char *iv = nx_ctx->priv.gcm.iv;
+ struct nx_gcm_rctx *rctx = aead_request_ctx(req);
+ char *iv = rctx->iv;
char *nonce = nx_ctx->priv.gcm.nonce;
memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
@@ -457,7 +459,8 @@
static int gcm4106_aes_nx_decrypt(struct aead_request *req)
{
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
- char *iv = nx_ctx->priv.gcm.iv;
+ struct nx_gcm_rctx *rctx = aead_request_ctx(req);
+ char *iv = rctx->iv;
char *nonce = nx_ctx->priv.gcm.nonce;
memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
diff --git a/drivers/crypto/nx/nx-aes-xcbc.c b/drivers/crypto/nx/nx-aes-xcbc.c
index 8c2faff..c2f7d4b 100644
--- a/drivers/crypto/nx/nx-aes-xcbc.c
+++ b/drivers/crypto/nx/nx-aes-xcbc.c
@@ -42,6 +42,7 @@
unsigned int key_len)
{
struct nx_crypto_ctx *nx_ctx = crypto_shash_ctx(desc);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
switch (key_len) {
case AES_KEYSIZE_128:
@@ -51,7 +52,7 @@
return -EINVAL;
}
- memcpy(nx_ctx->priv.xcbc.key, in_key, key_len);
+ memcpy(csbcpb->cpb.aes_xcbc.key, in_key, key_len);
return 0;
}
@@ -148,32 +149,29 @@
return rc;
}
-static int nx_xcbc_init(struct shash_desc *desc)
+static int nx_crypto_ctx_aes_xcbc_init2(struct crypto_tfm *tfm)
{
- struct xcbc_state *sctx = shash_desc_ctx(desc);
- struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
- struct nx_sg *out_sg;
- int len;
+ int err;
+
+ err = nx_crypto_ctx_aes_xcbc_init(tfm);
+ if (err)
+ return err;
nx_ctx_init(nx_ctx, HCOP_FC_AES);
- memset(sctx, 0, sizeof *sctx);
-
NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC;
- memcpy(csbcpb->cpb.aes_xcbc.key, nx_ctx->priv.xcbc.key, AES_BLOCK_SIZE);
- memset(nx_ctx->priv.xcbc.key, 0, sizeof *nx_ctx->priv.xcbc.key);
+ return 0;
+}
- len = AES_BLOCK_SIZE;
- out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
- &len, nx_ctx->ap->sglen);
+static int nx_xcbc_init(struct shash_desc *desc)
+{
+ struct xcbc_state *sctx = shash_desc_ctx(desc);
- if (len != AES_BLOCK_SIZE)
- return -EINVAL;
-
- nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+ memset(sctx, 0, sizeof *sctx);
return 0;
}
@@ -186,6 +184,7 @@
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
struct nx_sg *in_sg;
+ struct nx_sg *out_sg;
u32 to_process = 0, leftover, total;
unsigned int max_sg_len;
unsigned long irq_flags;
@@ -213,6 +212,17 @@
max_sg_len = min_t(u64, max_sg_len,
nx_ctx->ap->databytelen/NX_PAGE_SIZE);
+ data_len = AES_BLOCK_SIZE;
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
+ &len, nx_ctx->ap->sglen);
+
+ if (data_len != AES_BLOCK_SIZE) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
do {
to_process = total - to_process;
to_process = to_process & ~(AES_BLOCK_SIZE - 1);
@@ -235,8 +245,10 @@
(u8 *) sctx->buffer,
&data_len,
max_sg_len);
- if (data_len != sctx->count)
- return -EINVAL;
+ if (data_len != sctx->count) {
+ rc = -EINVAL;
+ goto out;
+ }
}
data_len = to_process - sctx->count;
@@ -245,8 +257,10 @@
&data_len,
max_sg_len);
- if (data_len != to_process - sctx->count)
- return -EINVAL;
+ if (data_len != to_process - sctx->count) {
+ rc = -EINVAL;
+ goto out;
+ }
nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
sizeof(struct nx_sg);
@@ -325,15 +339,19 @@
in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buffer,
&len, nx_ctx->ap->sglen);
- if (len != sctx->count)
- return -EINVAL;
+ if (len != sctx->count) {
+ rc = -EINVAL;
+ goto out;
+ }
len = AES_BLOCK_SIZE;
out_sg = nx_build_sg_list(nx_ctx->out_sg, out, &len,
nx_ctx->ap->sglen);
- if (len != AES_BLOCK_SIZE)
- return -EINVAL;
+ if (len != AES_BLOCK_SIZE) {
+ rc = -EINVAL;
+ goto out;
+ }
nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
@@ -372,7 +390,7 @@
.cra_blocksize = AES_BLOCK_SIZE,
.cra_module = THIS_MODULE,
.cra_ctxsize = sizeof(struct nx_crypto_ctx),
- .cra_init = nx_crypto_ctx_aes_xcbc_init,
+ .cra_init = nx_crypto_ctx_aes_xcbc_init2,
.cra_exit = nx_crypto_ctx_exit,
}
};
diff --git a/drivers/crypto/nx/nx-sha256.c b/drivers/crypto/nx/nx-sha256.c
index 4e91bdb..08f8d5c 100644
--- a/drivers/crypto/nx/nx-sha256.c
+++ b/drivers/crypto/nx/nx-sha256.c
@@ -29,34 +29,28 @@
#include "nx.h"
-static int nx_sha256_init(struct shash_desc *desc)
+static int nx_crypto_ctx_sha256_init(struct crypto_tfm *tfm)
{
- struct sha256_state *sctx = shash_desc_ctx(desc);
- struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
- struct nx_sg *out_sg;
- int len;
- u32 max_sg_len;
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+ int err;
+
+ err = nx_crypto_ctx_sha_init(tfm);
+ if (err)
+ return err;
nx_ctx_init(nx_ctx, HCOP_FC_SHA);
- memset(sctx, 0, sizeof *sctx);
-
nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA256];
NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA256);
- max_sg_len = min_t(u64, nx_ctx->ap->sglen,
- nx_driver.of.max_sg_len/sizeof(struct nx_sg));
- max_sg_len = min_t(u64, max_sg_len,
- nx_ctx->ap->databytelen/NX_PAGE_SIZE);
+ return 0;
+}
- len = SHA256_DIGEST_SIZE;
- out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
- &len, max_sg_len);
- nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+static int nx_sha256_init(struct shash_desc *desc) {
+ struct sha256_state *sctx = shash_desc_ctx(desc);
- if (len != SHA256_DIGEST_SIZE)
- return -EINVAL;
+ memset(sctx, 0, sizeof *sctx);
sctx->state[0] = __cpu_to_be32(SHA256_H0);
sctx->state[1] = __cpu_to_be32(SHA256_H1);
@@ -78,6 +72,7 @@
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
struct nx_sg *in_sg;
+ struct nx_sg *out_sg;
u64 to_process = 0, leftover, total;
unsigned long irq_flags;
int rc = 0;
@@ -108,6 +103,16 @@
max_sg_len = min_t(u64, max_sg_len,
nx_ctx->ap->databytelen/NX_PAGE_SIZE);
+ data_len = SHA256_DIGEST_SIZE;
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
+ &data_len, max_sg_len);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
+ if (data_len != SHA256_DIGEST_SIZE) {
+ rc = -EINVAL;
+ goto out;
+ }
+
do {
/*
* to_process: the SHA256_BLOCK_SIZE data chunk to process in
@@ -282,7 +287,7 @@
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
.cra_ctxsize = sizeof(struct nx_crypto_ctx),
- .cra_init = nx_crypto_ctx_sha_init,
+ .cra_init = nx_crypto_ctx_sha256_init,
.cra_exit = nx_crypto_ctx_exit,
}
};
diff --git a/drivers/crypto/nx/nx-sha512.c b/drivers/crypto/nx/nx-sha512.c
index e6a58d2..aff0fe5 100644
--- a/drivers/crypto/nx/nx-sha512.c
+++ b/drivers/crypto/nx/nx-sha512.c
@@ -28,34 +28,29 @@
#include "nx.h"
-static int nx_sha512_init(struct shash_desc *desc)
+static int nx_crypto_ctx_sha512_init(struct crypto_tfm *tfm)
{
- struct sha512_state *sctx = shash_desc_ctx(desc);
- struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
- struct nx_sg *out_sg;
- int len;
- u32 max_sg_len;
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+ int err;
+
+ err = nx_crypto_ctx_sha_init(tfm);
+ if (err)
+ return err;
nx_ctx_init(nx_ctx, HCOP_FC_SHA);
- memset(sctx, 0, sizeof *sctx);
-
nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA512];
NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA512);
- max_sg_len = min_t(u64, nx_ctx->ap->sglen,
- nx_driver.of.max_sg_len/sizeof(struct nx_sg));
- max_sg_len = min_t(u64, max_sg_len,
- nx_ctx->ap->databytelen/NX_PAGE_SIZE);
+ return 0;
+}
- len = SHA512_DIGEST_SIZE;
- out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
- &len, max_sg_len);
- nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+static int nx_sha512_init(struct shash_desc *desc)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
- if (len != SHA512_DIGEST_SIZE)
- return -EINVAL;
+ memset(sctx, 0, sizeof *sctx);
sctx->state[0] = __cpu_to_be64(SHA512_H0);
sctx->state[1] = __cpu_to_be64(SHA512_H1);
@@ -77,6 +72,7 @@
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
struct nx_sg *in_sg;
+ struct nx_sg *out_sg;
u64 to_process, leftover = 0, total;
unsigned long irq_flags;
int rc = 0;
@@ -107,6 +103,16 @@
max_sg_len = min_t(u64, max_sg_len,
nx_ctx->ap->databytelen/NX_PAGE_SIZE);
+ data_len = SHA512_DIGEST_SIZE;
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
+ &data_len, max_sg_len);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
+ if (data_len != SHA512_DIGEST_SIZE) {
+ rc = -EINVAL;
+ goto out;
+ }
+
do {
/*
* to_process: the SHA512_BLOCK_SIZE data chunk to process in
@@ -288,7 +294,7 @@
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_module = THIS_MODULE,
.cra_ctxsize = sizeof(struct nx_crypto_ctx),
- .cra_init = nx_crypto_ctx_sha_init,
+ .cra_init = nx_crypto_ctx_sha512_init,
.cra_exit = nx_crypto_ctx_exit,
}
};
diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
index f6198f2..4369713 100644
--- a/drivers/crypto/nx/nx.c
+++ b/drivers/crypto/nx/nx.c
@@ -713,12 +713,15 @@
/* entry points from the crypto tfm initializers */
int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm)
{
+ crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
+ sizeof(struct nx_ccm_rctx));
return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
NX_MODE_AES_CCM);
}
int nx_crypto_ctx_aes_gcm_init(struct crypto_aead *tfm)
{
+ crypto_aead_set_reqsize(tfm, sizeof(struct nx_gcm_rctx));
return nx_crypto_ctx_init(crypto_aead_ctx(tfm), NX_FC_AES,
NX_MODE_AES_GCM);
}
diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h
index de3ea87..cdff03a 100644
--- a/drivers/crypto/nx/nx.h
+++ b/drivers/crypto/nx/nx.h
@@ -2,6 +2,8 @@
#ifndef __NX_H__
#define __NX_H__
+#include <crypto/ctr.h>
+
#define NX_NAME "nx-crypto"
#define NX_STRING "IBM Power7+ Nest Accelerator Crypto Driver"
#define NX_VERSION "1.0"
@@ -91,8 +93,11 @@
#define NX_GCM4106_NONCE_LEN (4)
#define NX_GCM_CTR_OFFSET (12)
-struct nx_gcm_priv {
+struct nx_gcm_rctx {
u8 iv[16];
+};
+
+struct nx_gcm_priv {
u8 iauth_tag[16];
u8 nonce[NX_GCM4106_NONCE_LEN];
};
@@ -100,8 +105,11 @@
#define NX_CCM_AES_KEY_LEN (16)
#define NX_CCM4309_AES_KEY_LEN (19)
#define NX_CCM4309_NONCE_LEN (3)
-struct nx_ccm_priv {
+struct nx_ccm_rctx {
u8 iv[16];
+};
+
+struct nx_ccm_priv {
u8 b0[16];
u8 iauth_tag[16];
u8 oauth_tag[16];
@@ -113,7 +121,7 @@
};
struct nx_ctr_priv {
- u8 iv[16];
+ u8 nonce[CTR_RFC3686_NONCE_SIZE];
};
struct nx_crypto_ctx {
diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index 4630709..0a70e46 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -536,9 +536,6 @@
dmaengine_terminate_all(dd->dma_lch_in);
dmaengine_terminate_all(dd->dma_lch_out);
- dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
- dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE);
-
return err;
}
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index c7dcfe4..0429040 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -88,7 +88,7 @@
struct ib_ah *ah;
struct ib_mad_send_wr_private *mad_send_wr;
- if (device->node_type == RDMA_NODE_IB_SWITCH)
+ if (rdma_cap_ib_switch(device))
port_priv = ib_get_agent_port(device, 0);
else
port_priv = ib_get_agent_port(device, port_num);
@@ -122,7 +122,7 @@
memcpy(send_buf->mad, mad_hdr, resp_mad_len);
send_buf->ah = ah;
- if (device->node_type == RDMA_NODE_IB_SWITCH) {
+ if (rdma_cap_ib_switch(device)) {
mad_send_wr = container_of(send_buf,
struct ib_mad_send_wr_private,
send_buf);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index dbddddd..3a972eb 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -169,6 +169,7 @@
struct ib_device *ib_device;
struct device *device;
u8 ack_delay;
+ int going_down;
struct cm_port *port[0];
};
@@ -805,6 +806,11 @@
{
int wait_time;
unsigned long flags;
+ struct cm_device *cm_dev;
+
+ cm_dev = ib_get_client_data(cm_id_priv->id.device, &cm_client);
+ if (!cm_dev)
+ return;
spin_lock_irqsave(&cm.lock, flags);
cm_cleanup_timewait(cm_id_priv->timewait_info);
@@ -818,8 +824,14 @@
*/
cm_id_priv->id.state = IB_CM_TIMEWAIT;
wait_time = cm_convert_to_ms(cm_id_priv->av.timeout);
- queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
- msecs_to_jiffies(wait_time));
+
+ /* Check if the device started its remove_one */
+ spin_lock_irq(&cm.lock);
+ if (!cm_dev->going_down)
+ queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
+ msecs_to_jiffies(wait_time));
+ spin_unlock_irq(&cm.lock);
+
cm_id_priv->timewait_info = NULL;
}
@@ -3305,6 +3317,11 @@
struct cm_work *work;
unsigned long flags;
int ret = 0;
+ struct cm_device *cm_dev;
+
+ cm_dev = ib_get_client_data(cm_id->device, &cm_client);
+ if (!cm_dev)
+ return -ENODEV;
work = kmalloc(sizeof *work, GFP_ATOMIC);
if (!work)
@@ -3343,7 +3360,17 @@
work->remote_id = cm_id->remote_id;
work->mad_recv_wc = NULL;
work->cm_event.event = IB_CM_USER_ESTABLISHED;
- queue_delayed_work(cm.wq, &work->work, 0);
+
+ /* Check if the device started its remove_one */
+ spin_lock_irq(&cm.lock);
+ if (!cm_dev->going_down) {
+ queue_delayed_work(cm.wq, &work->work, 0);
+ } else {
+ kfree(work);
+ ret = -ENODEV;
+ }
+ spin_unlock_irq(&cm.lock);
+
out:
return ret;
}
@@ -3394,6 +3421,7 @@
enum ib_cm_event_type event;
u16 attr_id;
int paths = 0;
+ int going_down = 0;
switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) {
case CM_REQ_ATTR_ID:
@@ -3452,7 +3480,19 @@
work->cm_event.event = event;
work->mad_recv_wc = mad_recv_wc;
work->port = port;
- queue_delayed_work(cm.wq, &work->work, 0);
+
+ /* Check if the device started its remove_one */
+ spin_lock_irq(&cm.lock);
+ if (!port->cm_dev->going_down)
+ queue_delayed_work(cm.wq, &work->work, 0);
+ else
+ going_down = 1;
+ spin_unlock_irq(&cm.lock);
+
+ if (going_down) {
+ kfree(work);
+ ib_free_recv_mad(mad_recv_wc);
+ }
}
static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
@@ -3771,7 +3811,7 @@
cm_dev->ib_device = ib_device;
cm_get_ack_delay(cm_dev);
-
+ cm_dev->going_down = 0;
cm_dev->device = device_create(&cm_class, &ib_device->dev,
MKDEV(0, 0), NULL,
"%s", ib_device->name);
@@ -3864,14 +3904,23 @@
list_del(&cm_dev->list);
write_unlock_irqrestore(&cm.device_lock, flags);
+ spin_lock_irq(&cm.lock);
+ cm_dev->going_down = 1;
+ spin_unlock_irq(&cm.lock);
+
for (i = 1; i <= ib_device->phys_port_cnt; i++) {
if (!rdma_cap_ib_cm(ib_device, i))
continue;
port = cm_dev->port[i-1];
ib_modify_port(ib_device, port->port_num, 0, &port_modify);
- ib_unregister_mad_agent(port->mad_agent);
+ /*
+ * We flush the queue here after the going_down set, this
+ * verify that no new works will be queued in the recv handler,
+ * after that we can call the unregister_mad_agent
+ */
flush_workqueue(cm.wq);
+ ib_unregister_mad_agent(port->mad_agent);
cm_remove_port_fs(port);
}
device_unregister(cm_dev->device);
diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c
index e6ffa2e..22a3abe 100644
--- a/drivers/infiniband/core/iwpm_msg.c
+++ b/drivers/infiniband/core/iwpm_msg.c
@@ -67,7 +67,8 @@
err_str = "Invalid port mapper client";
goto pid_query_error;
}
- if (iwpm_registered_client(nl_client))
+ if (iwpm_check_registration(nl_client, IWPM_REG_VALID) ||
+ iwpm_user_pid == IWPM_PID_UNAVAILABLE)
return 0;
skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);
if (!skb) {
@@ -106,7 +107,6 @@
ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
if (ret) {
skb = NULL; /* skb is freed in the netlink send-op handling */
- iwpm_set_registered(nl_client, 1);
iwpm_user_pid = IWPM_PID_UNAVAILABLE;
err_str = "Unable to send a nlmsg";
goto pid_query_error;
@@ -144,12 +144,12 @@
err_str = "Invalid port mapper client";
goto add_mapping_error;
}
- if (!iwpm_registered_client(nl_client)) {
+ if (!iwpm_valid_pid())
+ return 0;
+ if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
err_str = "Unregistered port mapper client";
goto add_mapping_error;
}
- if (!iwpm_valid_pid())
- return 0;
skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);
if (!skb) {
err_str = "Unable to create a nlmsg";
@@ -214,12 +214,12 @@
err_str = "Invalid port mapper client";
goto query_mapping_error;
}
- if (!iwpm_registered_client(nl_client)) {
+ if (!iwpm_valid_pid())
+ return 0;
+ if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
err_str = "Unregistered port mapper client";
goto query_mapping_error;
}
- if (!iwpm_valid_pid())
- return 0;
ret = -ENOMEM;
skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);
if (!skb) {
@@ -288,12 +288,12 @@
err_str = "Invalid port mapper client";
goto remove_mapping_error;
}
- if (!iwpm_registered_client(nl_client)) {
+ if (!iwpm_valid_pid())
+ return 0;
+ if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) {
err_str = "Unregistered port mapper client";
goto remove_mapping_error;
}
- if (!iwpm_valid_pid())
- return 0;
skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);
if (!skb) {
ret = -ENOMEM;
@@ -388,7 +388,7 @@
pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
__func__, iwpm_user_pid);
if (iwpm_valid_client(nl_client))
- iwpm_set_registered(nl_client, 1);
+ iwpm_set_registration(nl_client, IWPM_REG_VALID);
register_pid_response_exit:
nlmsg_request->request_done = 1;
/* always for found nlmsg_request */
@@ -644,7 +644,6 @@
{
struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
const char *msg_type = "Mapping Info response";
- int iwpm_pid;
u8 nl_client;
char *iwpm_name;
u16 iwpm_version;
@@ -669,14 +668,14 @@
__func__, nl_client);
return ret;
}
- iwpm_set_registered(nl_client, 0);
+ iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
+ iwpm_user_pid = cb->nlh->nlmsg_pid;
if (!iwpm_mapinfo_available())
return 0;
- iwpm_pid = cb->nlh->nlmsg_pid;
pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
- __func__, iwpm_pid);
- ret = iwpm_send_mapinfo(nl_client, iwpm_pid);
+ __func__, iwpm_user_pid);
+ ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid);
return ret;
}
EXPORT_SYMBOL(iwpm_mapping_info_cb);
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
index a626795..5fb089e 100644
--- a/drivers/infiniband/core/iwpm_util.c
+++ b/drivers/infiniband/core/iwpm_util.c
@@ -78,6 +78,7 @@
mutex_unlock(&iwpm_admin_lock);
if (!ret) {
iwpm_set_valid(nl_client, 1);
+ iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
pr_debug("%s: Mapinfo and reminfo tables are created\n",
__func__);
}
@@ -106,6 +107,7 @@
}
mutex_unlock(&iwpm_admin_lock);
iwpm_set_valid(nl_client, 0);
+ iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
return 0;
}
EXPORT_SYMBOL(iwpm_exit);
@@ -397,17 +399,23 @@
}
/* valid client */
-int iwpm_registered_client(u8 nl_client)
+u32 iwpm_get_registration(u8 nl_client)
{
return iwpm_admin.reg_list[nl_client];
}
/* valid client */
-void iwpm_set_registered(u8 nl_client, int reg)
+void iwpm_set_registration(u8 nl_client, u32 reg)
{
iwpm_admin.reg_list[nl_client] = reg;
}
+/* valid client */
+u32 iwpm_check_registration(u8 nl_client, u32 reg)
+{
+ return (iwpm_get_registration(nl_client) & reg);
+}
+
int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr,
struct sockaddr_storage *b_sockaddr)
{
diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h
index ee2d9ff..b7b9e19 100644
--- a/drivers/infiniband/core/iwpm_util.h
+++ b/drivers/infiniband/core/iwpm_util.h
@@ -58,6 +58,10 @@
#define IWPM_PID_UNDEFINED -1
#define IWPM_PID_UNAVAILABLE -2
+#define IWPM_REG_UNDEF 0x01
+#define IWPM_REG_VALID 0x02
+#define IWPM_REG_INCOMPL 0x04
+
struct iwpm_nlmsg_request {
struct list_head inprocess_list;
__u32 nlmsg_seq;
@@ -88,7 +92,7 @@
atomic_t refcount;
atomic_t nlmsg_seq;
int client_list[RDMA_NL_NUM_CLIENTS];
- int reg_list[RDMA_NL_NUM_CLIENTS];
+ u32 reg_list[RDMA_NL_NUM_CLIENTS];
};
/**
@@ -159,19 +163,31 @@
void iwpm_set_valid(u8 nl_client, int valid);
/**
- * iwpm_registered_client - Check if the port mapper client is registered
+ * iwpm_check_registration - Check if the client registration
+ * matches the given one
* @nl_client: The index of the netlink client
+ * @reg: The given registration type to compare with
*
* Call iwpm_register_pid() to register a client
+ * Returns true if the client registration matches reg,
+ * otherwise returns false
*/
-int iwpm_registered_client(u8 nl_client);
+u32 iwpm_check_registration(u8 nl_client, u32 reg);
/**
- * iwpm_set_registered - Set the port mapper client to registered or not
+ * iwpm_set_registration - Set the client registration
* @nl_client: The index of the netlink client
- * @reg: 1 if registered or 0 if not
+ * @reg: Registration type to set
*/
-void iwpm_set_registered(u8 nl_client, int reg);
+void iwpm_set_registration(u8 nl_client, u32 reg);
+
+/**
+ * iwpm_get_registration
+ * @nl_client: The index of the netlink client
+ *
+ * Returns the client registration type
+ */
+u32 iwpm_get_registration(u8 nl_client);
/**
* iwpm_send_mapinfo - Send local and mapped IPv4/IPv6 address info of
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index a4b1466..786fc51 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -769,7 +769,7 @@
bool opa = rdma_cap_opa_mad(mad_agent_priv->qp_info->port_priv->device,
mad_agent_priv->qp_info->port_priv->port_num);
- if (device->node_type == RDMA_NODE_IB_SWITCH &&
+ if (rdma_cap_ib_switch(device) &&
smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
port_num = send_wr->wr.ud.port_num;
else
@@ -787,14 +787,15 @@
if ((opa_get_smp_direction(opa_smp)
? opa_smp->route.dr.dr_dlid : opa_smp->route.dr.dr_slid) ==
OPA_LID_PERMISSIVE &&
- opa_smi_handle_dr_smp_send(opa_smp, device->node_type,
+ opa_smi_handle_dr_smp_send(opa_smp,
+ rdma_cap_ib_switch(device),
port_num) == IB_SMI_DISCARD) {
ret = -EINVAL;
dev_err(&device->dev, "OPA Invalid directed route\n");
goto out;
}
opa_drslid = be32_to_cpu(opa_smp->route.dr.dr_slid);
- if (opa_drslid != OPA_LID_PERMISSIVE &&
+ if (opa_drslid != be32_to_cpu(OPA_LID_PERMISSIVE) &&
opa_drslid & 0xffff0000) {
ret = -EINVAL;
dev_err(&device->dev, "OPA Invalid dr_slid 0x%x\n",
@@ -810,7 +811,7 @@
} else {
if ((ib_get_smp_direction(smp) ? smp->dr_dlid : smp->dr_slid) ==
IB_LID_PERMISSIVE &&
- smi_handle_dr_smp_send(smp, device->node_type, port_num) ==
+ smi_handle_dr_smp_send(smp, rdma_cap_ib_switch(device), port_num) ==
IB_SMI_DISCARD) {
ret = -EINVAL;
dev_err(&device->dev, "Invalid directed route\n");
@@ -2030,7 +2031,7 @@
struct ib_smp *smp = (struct ib_smp *)recv->mad;
if (smi_handle_dr_smp_recv(smp,
- port_priv->device->node_type,
+ rdma_cap_ib_switch(port_priv->device),
port_num,
port_priv->device->phys_port_cnt) ==
IB_SMI_DISCARD)
@@ -2042,13 +2043,13 @@
if (retsmi == IB_SMI_SEND) { /* don't forward */
if (smi_handle_dr_smp_send(smp,
- port_priv->device->node_type,
+ rdma_cap_ib_switch(port_priv->device),
port_num) == IB_SMI_DISCARD)
return IB_SMI_DISCARD;
if (smi_check_local_smp(smp, port_priv->device) == IB_SMI_DISCARD)
return IB_SMI_DISCARD;
- } else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) {
+ } else if (rdma_cap_ib_switch(port_priv->device)) {
/* forward case for switches */
memcpy(response, recv, mad_priv_size(response));
response->header.recv_wc.wc = &response->header.wc;
@@ -2115,7 +2116,7 @@
struct opa_smp *smp = (struct opa_smp *)recv->mad;
if (opa_smi_handle_dr_smp_recv(smp,
- port_priv->device->node_type,
+ rdma_cap_ib_switch(port_priv->device),
port_num,
port_priv->device->phys_port_cnt) ==
IB_SMI_DISCARD)
@@ -2127,7 +2128,7 @@
if (retsmi == IB_SMI_SEND) { /* don't forward */
if (opa_smi_handle_dr_smp_send(smp,
- port_priv->device->node_type,
+ rdma_cap_ib_switch(port_priv->device),
port_num) == IB_SMI_DISCARD)
return IB_SMI_DISCARD;
@@ -2135,7 +2136,7 @@
IB_SMI_DISCARD)
return IB_SMI_DISCARD;
- } else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) {
+ } else if (rdma_cap_ib_switch(port_priv->device)) {
/* forward case for switches */
memcpy(response, recv, mad_priv_size(response));
response->header.recv_wc.wc = &response->header.wc;
@@ -2235,7 +2236,7 @@
goto out;
}
- if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH)
+ if (rdma_cap_ib_switch(port_priv->device))
port_num = wc->port_num;
else
port_num = port_priv->port_num;
@@ -3297,17 +3298,11 @@
static void ib_mad_init_device(struct ib_device *device)
{
- int start, end, i;
+ int start, i;
- if (device->node_type == RDMA_NODE_IB_SWITCH) {
- start = 0;
- end = 0;
- } else {
- start = 1;
- end = device->phys_port_cnt;
- }
+ start = rdma_start_port(device);
- for (i = start; i <= end; i++) {
+ for (i = start; i <= rdma_end_port(device); i++) {
if (!rdma_cap_ib_mad(device, i))
continue;
@@ -3342,17 +3337,9 @@
static void ib_mad_remove_device(struct ib_device *device)
{
- int start, end, i;
+ int i;
- if (device->node_type == RDMA_NODE_IB_SWITCH) {
- start = 0;
- end = 0;
- } else {
- start = 1;
- end = device->phys_port_cnt;
- }
-
- for (i = start; i <= end; i++) {
+ for (i = rdma_start_port(device); i <= rdma_end_port(device); i++) {
if (!rdma_cap_ib_mad(device, i))
continue;
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index 1244f02..2cb865c 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -812,12 +812,8 @@
if (!dev)
return;
- if (device->node_type == RDMA_NODE_IB_SWITCH)
- dev->start_port = dev->end_port = 0;
- else {
- dev->start_port = 1;
- dev->end_port = device->phys_port_cnt;
- }
+ dev->start_port = rdma_start_port(device);
+ dev->end_port = rdma_end_port(device);
for (i = 0; i <= dev->end_port - dev->start_port; i++) {
if (!rdma_cap_ib_mcast(device, dev->start_port + i))
diff --git a/drivers/infiniband/core/opa_smi.h b/drivers/infiniband/core/opa_smi.h
index 62d91bf..3bfab35 100644
--- a/drivers/infiniband/core/opa_smi.h
+++ b/drivers/infiniband/core/opa_smi.h
@@ -39,12 +39,12 @@
#include "smi.h"
-enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, u8 node_type,
+enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch,
int port_num, int phys_port_cnt);
int opa_smi_get_fwd_port(struct opa_smp *smp);
extern enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp);
extern enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp,
- u8 node_type, int port_num);
+ bool is_switch, int port_num);
/*
* Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 0fae850..ca919f4 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1156,12 +1156,8 @@
int s, e, i;
int count = 0;
- if (device->node_type == RDMA_NODE_IB_SWITCH)
- s = e = 0;
- else {
- s = 1;
- e = device->phys_port_cnt;
- }
+ s = rdma_start_port(device);
+ e = rdma_end_port(device);
sa_dev = kzalloc(sizeof *sa_dev +
(e - s + 1) * sizeof (struct ib_sa_port),
diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c
index 368a561..f19b238 100644
--- a/drivers/infiniband/core/smi.c
+++ b/drivers/infiniband/core/smi.c
@@ -41,7 +41,7 @@
#include "smi.h"
#include "opa_smi.h"
-static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num,
+static enum smi_action __smi_handle_dr_smp_send(bool is_switch, int port_num,
u8 *hop_ptr, u8 hop_cnt,
const u8 *initial_path,
const u8 *return_path,
@@ -64,7 +64,7 @@
/* C14-9:2 */
if (*hop_ptr && *hop_ptr < hop_cnt) {
- if (node_type != RDMA_NODE_IB_SWITCH)
+ if (!is_switch)
return IB_SMI_DISCARD;
/* return_path set when received */
@@ -77,7 +77,7 @@
if (*hop_ptr == hop_cnt) {
/* return_path set when received */
(*hop_ptr)++;
- return (node_type == RDMA_NODE_IB_SWITCH ||
+ return (is_switch ||
dr_dlid_is_permissive ?
IB_SMI_HANDLE : IB_SMI_DISCARD);
}
@@ -96,7 +96,7 @@
/* C14-13:2 */
if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
- if (node_type != RDMA_NODE_IB_SWITCH)
+ if (!is_switch)
return IB_SMI_DISCARD;
(*hop_ptr)--;
@@ -108,7 +108,7 @@
if (*hop_ptr == 1) {
(*hop_ptr)--;
/* C14-13:3 -- SMPs destined for SM shouldn't be here */
- return (node_type == RDMA_NODE_IB_SWITCH ||
+ return (is_switch ||
dr_slid_is_permissive ?
IB_SMI_HANDLE : IB_SMI_DISCARD);
}
@@ -127,9 +127,9 @@
* Return IB_SMI_DISCARD if the SMP should be discarded
*/
enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
- u8 node_type, int port_num)
+ bool is_switch, int port_num)
{
- return __smi_handle_dr_smp_send(node_type, port_num,
+ return __smi_handle_dr_smp_send(is_switch, port_num,
&smp->hop_ptr, smp->hop_cnt,
smp->initial_path,
smp->return_path,
@@ -139,9 +139,9 @@
}
enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp,
- u8 node_type, int port_num)
+ bool is_switch, int port_num)
{
- return __smi_handle_dr_smp_send(node_type, port_num,
+ return __smi_handle_dr_smp_send(is_switch, port_num,
&smp->hop_ptr, smp->hop_cnt,
smp->route.dr.initial_path,
smp->route.dr.return_path,
@@ -152,7 +152,7 @@
OPA_LID_PERMISSIVE);
}
-static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num,
+static enum smi_action __smi_handle_dr_smp_recv(bool is_switch, int port_num,
int phys_port_cnt,
u8 *hop_ptr, u8 hop_cnt,
const u8 *initial_path,
@@ -173,7 +173,7 @@
/* C14-9:2 -- intermediate hop */
if (*hop_ptr && *hop_ptr < hop_cnt) {
- if (node_type != RDMA_NODE_IB_SWITCH)
+ if (!is_switch)
return IB_SMI_DISCARD;
return_path[*hop_ptr] = port_num;
@@ -188,7 +188,7 @@
return_path[*hop_ptr] = port_num;
/* hop_ptr updated when sending */
- return (node_type == RDMA_NODE_IB_SWITCH ||
+ return (is_switch ||
dr_dlid_is_permissive ?
IB_SMI_HANDLE : IB_SMI_DISCARD);
}
@@ -208,7 +208,7 @@
/* C14-13:2 */
if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
- if (node_type != RDMA_NODE_IB_SWITCH)
+ if (!is_switch)
return IB_SMI_DISCARD;
/* hop_ptr updated when sending */
@@ -224,8 +224,7 @@
return IB_SMI_HANDLE;
}
/* hop_ptr updated when sending */
- return (node_type == RDMA_NODE_IB_SWITCH ?
- IB_SMI_HANDLE : IB_SMI_DISCARD);
+ return (is_switch ? IB_SMI_HANDLE : IB_SMI_DISCARD);
}
/* C14-13:4 -- hop_ptr = 0 -> give to SM */
@@ -238,10 +237,10 @@
* Adjust information for a received SMP
* Return IB_SMI_DISCARD if the SMP should be dropped
*/
-enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
+enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch,
int port_num, int phys_port_cnt)
{
- return __smi_handle_dr_smp_recv(node_type, port_num, phys_port_cnt,
+ return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
&smp->hop_ptr, smp->hop_cnt,
smp->initial_path,
smp->return_path,
@@ -254,10 +253,10 @@
* Adjust information for a received SMP
* Return IB_SMI_DISCARD if the SMP should be dropped
*/
-enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, u8 node_type,
+enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch,
int port_num, int phys_port_cnt)
{
- return __smi_handle_dr_smp_recv(node_type, port_num, phys_port_cnt,
+ return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
&smp->hop_ptr, smp->hop_cnt,
smp->route.dr.initial_path,
smp->route.dr.return_path,
diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h
index aff96ba..33c91c8 100644
--- a/drivers/infiniband/core/smi.h
+++ b/drivers/infiniband/core/smi.h
@@ -51,12 +51,12 @@
IB_SMI_FORWARD /* SMP should be forwarded (for switches only) */
};
-enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
+enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch,
int port_num, int phys_port_cnt);
int smi_get_fwd_port(struct ib_smp *smp);
extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp);
extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
- u8 node_type, int port_num);
+ bool is_switch, int port_num);
/*
* Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index ed6b6c8..0b84a9c 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -870,7 +870,7 @@
goto err_put;
}
- if (device->node_type == RDMA_NODE_IB_SWITCH) {
+ if (rdma_cap_ib_switch(device)) {
ret = add_port(device, 0, port_callback);
if (ret)
goto err_put;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 62c24b1..0094810 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1193,6 +1193,7 @@
return 0;
}
+static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES);
static void ib_ucm_release_dev(struct device *dev)
{
struct ib_ucm_device *ucm_dev;
@@ -1202,7 +1203,7 @@
if (ucm_dev->devnum < IB_UCM_MAX_DEVICES)
clear_bit(ucm_dev->devnum, dev_map);
else
- clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, dev_map);
+ clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, overflow_map);
kfree(ucm_dev);
}
@@ -1226,7 +1227,6 @@
static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
static dev_t overflow_maj;
-static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES);
static int find_overflow_devnum(void)
{
int ret;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index ad45469..29b2121 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -1354,10 +1354,10 @@
/* Acquire mutex's based on pointer comparison to prevent deadlock. */
if (file1 < file2) {
mutex_lock(&file1->mut);
- mutex_lock(&file2->mut);
+ mutex_lock_nested(&file2->mut, SINGLE_DEPTH_NESTING);
} else {
mutex_lock(&file2->mut);
- mutex_lock(&file1->mut);
+ mutex_lock_nested(&file1->mut, SINGLE_DEPTH_NESTING);
}
}
@@ -1616,6 +1616,7 @@
device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
misc_deregister(&ucma_misc);
idr_destroy(&ctx_idr);
+ idr_destroy(&multicast_idr);
}
module_init(ucma_init);
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c
index 12b5bc2..376b031 100644
--- a/drivers/infiniband/hw/ehca/ehca_sqp.c
+++ b/drivers/infiniband/hw/ehca/ehca_sqp.c
@@ -226,8 +226,9 @@
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
- BUG_ON(in_mad_size != sizeof(*in_mad) ||
- *out_mad_size != sizeof(*out_mad));
+ if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
+ *out_mad_size != sizeof(*out_mad)))
+ return IB_MAD_RESULT_FAILURE;
if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc)
return IB_MAD_RESULT_FAILURE;
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index 948188e..ad3a926 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -1499,8 +1499,9 @@
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
- BUG_ON(in_mad_size != sizeof(*in_mad) ||
- *out_mad_size != sizeof(*out_mad));
+ if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
+ *out_mad_size != sizeof(*out_mad)))
+ return IB_MAD_RESULT_FAILURE;
switch (in_mad->mad_hdr.mgmt_class) {
case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index 48253b8..30ba49c 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -2044,9 +2044,9 @@
spin_lock_init(&idev->qp_table.lock);
spin_lock_init(&idev->lk_table.lock);
- idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE);
+ idev->sm_lid = be16_to_cpu(IB_LID_PERMISSIVE);
/* Set the prefix to the default value (see ch. 4.1.1) */
- idev->gid_prefix = __constant_cpu_to_be64(0xfe80000000000000ULL);
+ idev->gid_prefix = cpu_to_be64(0xfe80000000000000ULL);
ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size);
if (ret)
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 85a50df..68b3dfa 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -860,21 +860,31 @@
struct mlx4_ib_dev *dev = to_mdev(ibdev);
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
+ enum rdma_link_layer link = rdma_port_get_link_layer(ibdev, port_num);
- BUG_ON(in_mad_size != sizeof(*in_mad) ||
- *out_mad_size != sizeof(*out_mad));
+ if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
+ *out_mad_size != sizeof(*out_mad)))
+ return IB_MAD_RESULT_FAILURE;
- switch (rdma_port_get_link_layer(ibdev, port_num)) {
- case IB_LINK_LAYER_INFINIBAND:
- if (!mlx4_is_slave(dev->dev))
- return ib_process_mad(ibdev, mad_flags, port_num, in_wc,
- in_grh, in_mad, out_mad);
- case IB_LINK_LAYER_ETHERNET:
- return iboe_process_mad(ibdev, mad_flags, port_num, in_wc,
- in_grh, in_mad, out_mad);
- default:
- return -EINVAL;
+ /* iboe_process_mad() which uses the HCA flow-counters to implement IB PMA
+ * queries, should be called only by VFs and for that specific purpose
+ */
+ if (link == IB_LINK_LAYER_INFINIBAND) {
+ if (mlx4_is_slave(dev->dev) &&
+ in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT &&
+ in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS)
+ return iboe_process_mad(ibdev, mad_flags, port_num, in_wc,
+ in_grh, in_mad, out_mad);
+
+ return ib_process_mad(ibdev, mad_flags, port_num, in_wc,
+ in_grh, in_mad, out_mad);
}
+
+ if (link == IB_LINK_LAYER_ETHERNET)
+ return iboe_process_mad(ibdev, mad_flags, port_num, in_wc,
+ in_grh, in_mad, out_mad);
+
+ return -EINVAL;
}
static void send_handler(struct ib_mad_agent *agent,
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 067a691..8be6db8 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -253,14 +253,15 @@
props->hca_core_clock = dev->dev->caps.hca_core_clock * 1000UL;
props->timestamp_mask = 0xFFFFFFFFFFFFULL;
- err = mlx4_get_internal_clock_params(dev->dev, &clock_params);
- if (err)
- goto out;
+ if (!mlx4_is_slave(dev->dev))
+ err = mlx4_get_internal_clock_params(dev->dev, &clock_params);
if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
- resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE;
resp.response_length += sizeof(resp.hca_core_clock_offset);
- resp.comp_mask |= QUERY_DEVICE_RESP_MASK_TIMESTAMP;
+ if (!err && !mlx4_is_slave(dev->dev)) {
+ resp.comp_mask |= QUERY_DEVICE_RESP_MASK_TIMESTAMP;
+ resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE;
+ }
}
if (uhw->outlen) {
@@ -2669,31 +2670,33 @@
dm = kcalloc(ports, sizeof(*dm), GFP_ATOMIC);
if (!dm) {
pr_err("failed to allocate memory for tunneling qp update\n");
- goto out;
+ return;
}
for (i = 0; i < ports; i++) {
dm[i] = kmalloc(sizeof (struct mlx4_ib_demux_work), GFP_ATOMIC);
if (!dm[i]) {
pr_err("failed to allocate memory for tunneling qp update work struct\n");
- for (i = 0; i < dev->caps.num_ports; i++) {
- if (dm[i])
- kfree(dm[i]);
- }
+ while (--i >= 0)
+ kfree(dm[i]);
goto out;
}
- }
- /* initialize or tear down tunnel QPs for the slave */
- for (i = 0; i < ports; i++) {
INIT_WORK(&dm[i]->work, mlx4_ib_tunnels_update_work);
dm[i]->port = first_port + i + 1;
dm[i]->slave = slave;
dm[i]->do_init = do_init;
dm[i]->dev = ibdev;
- spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags);
- if (!ibdev->sriov.is_going_down)
+ }
+ /* initialize or tear down tunnel QPs for the slave */
+ spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags);
+ if (!ibdev->sriov.is_going_down) {
+ for (i = 0; i < ports; i++)
queue_work(ibdev->sriov.demux[i].ud_wq, &dm[i]->work);
spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags);
+ } else {
+ spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags);
+ for (i = 0; i < ports; i++)
+ kfree(dm[i]);
}
out:
kfree(dm);
diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c
index 01fc97d..b84d13a 100644
--- a/drivers/infiniband/hw/mlx5/mad.c
+++ b/drivers/infiniband/hw/mlx5/mad.c
@@ -68,8 +68,9 @@
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
- BUG_ON(in_mad_size != sizeof(*in_mad) ||
- *out_mad_size != sizeof(*out_mad));
+ if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
+ *out_mad_size != sizeof(*out_mad)))
+ return IB_MAD_RESULT_FAILURE;
slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 6b2418b..7c3f2fb 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -209,8 +209,9 @@
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
- BUG_ON(in_mad_size != sizeof(*in_mad) ||
- *out_mad_size != sizeof(*out_mad));
+ if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
+ *out_mad_size != sizeof(*out_mad)))
+ return IB_MAD_RESULT_FAILURE;
/* Forward locally generated traps to the SM */
if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP &&
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 9047af4..8a3ad17 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1520,8 +1520,9 @@
int rc = arpindex;
struct net_device *netdev;
struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
+ __be32 dst_ipaddr = htonl(dst_ip);
- rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0);
+ rt = ip_route_output(&init_net, dst_ipaddr, nesvnic->local_ipaddr, 0, 0);
if (IS_ERR(rt)) {
printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
__func__, dst_ip);
@@ -1533,7 +1534,7 @@
else
netdev = nesvnic->netdev;
- neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, netdev);
+ neigh = dst_neigh_lookup(&rt->dst, &dst_ipaddr);
rcu_read_lock();
if (neigh) {
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 02120d3..4713dd7 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -3861,7 +3861,7 @@
(((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |
(((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(
- (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);
+ (((u32)mac_addr[0]) << 8) | (u32)mac_addr[1]);
} else {
cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
index 4bafa15..29b2767 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
@@ -215,8 +215,9 @@
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
- BUG_ON(in_mad_size != sizeof(*in_mad) ||
- *out_mad_size != sizeof(*out_mad));
+ if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
+ *out_mad_size != sizeof(*out_mad)))
+ return IB_MAD_RESULT_FAILURE;
switch (in_mad->mad_hdr.mgmt_class) {
case IB_MGMT_CLASS_PERF_MGMT:
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index 8a1398b..d98a707 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -696,6 +696,7 @@
ocrdma_unregister_inet6addr_notifier();
ocrdma_unregister_inetaddr_notifier();
ocrdma_rem_debugfs();
+ idr_destroy(&ocrdma_dev_id);
}
module_init(ocrdma_init_module);
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index 05e3242..9625e7c 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -2412,8 +2412,9 @@
const struct ib_mad *in_mad = (const struct ib_mad *)in;
struct ib_mad *out_mad = (struct ib_mad *)out;
- BUG_ON(in_mad_size != sizeof(*in_mad) ||
- *out_mad_size != sizeof(*out_mad));
+ if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
+ *out_mad_size != sizeof(*out_mad)))
+ return IB_MAD_RESULT_FAILURE;
switch (in_mad->mad_hdr.mgmt_class) {
case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index bd94b0a..79859c4 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -239,7 +239,7 @@
struct net_device *dev;
struct ipoib_neigh *neigh;
struct ipoib_path *path;
- struct ipoib_cm_tx_buf *tx_ring;
+ struct ipoib_tx_buf *tx_ring;
unsigned tx_head;
unsigned tx_tail;
unsigned long flags;
@@ -504,6 +504,33 @@
void ipoib_mcast_dev_down(struct net_device *dev);
void ipoib_mcast_dev_flush(struct net_device *dev);
+int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req);
+void ipoib_dma_unmap_tx(struct ipoib_dev_priv *priv,
+ struct ipoib_tx_buf *tx_req);
+
+static inline void ipoib_build_sge(struct ipoib_dev_priv *priv,
+ struct ipoib_tx_buf *tx_req)
+{
+ int i, off;
+ struct sk_buff *skb = tx_req->skb;
+ skb_frag_t *frags = skb_shinfo(skb)->frags;
+ int nr_frags = skb_shinfo(skb)->nr_frags;
+ u64 *mapping = tx_req->mapping;
+
+ if (skb_headlen(skb)) {
+ priv->tx_sge[0].addr = mapping[0];
+ priv->tx_sge[0].length = skb_headlen(skb);
+ off = 1;
+ } else
+ off = 0;
+
+ for (i = 0; i < nr_frags; ++i) {
+ priv->tx_sge[i + off].addr = mapping[i + off];
+ priv->tx_sge[i + off].length = skb_frag_size(&frags[i]);
+ }
+ priv->tx_wr.num_sge = nr_frags + off;
+}
+
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev);
int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index cf32a778..ee39be6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -694,14 +694,12 @@
static inline int post_send(struct ipoib_dev_priv *priv,
struct ipoib_cm_tx *tx,
unsigned int wr_id,
- u64 addr, int len)
+ struct ipoib_tx_buf *tx_req)
{
struct ib_send_wr *bad_wr;
- priv->tx_sge[0].addr = addr;
- priv->tx_sge[0].length = len;
+ ipoib_build_sge(priv, tx_req);
- priv->tx_wr.num_sge = 1;
priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM;
return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr);
@@ -710,8 +708,7 @@
void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ipoib_cm_tx_buf *tx_req;
- u64 addr;
+ struct ipoib_tx_buf *tx_req;
int rc;
if (unlikely(skb->len > tx->mtu)) {
@@ -735,24 +732,21 @@
*/
tx_req = &tx->tx_ring[tx->tx_head & (ipoib_sendq_size - 1)];
tx_req->skb = skb;
- addr = ib_dma_map_single(priv->ca, skb->data, skb->len, DMA_TO_DEVICE);
- if (unlikely(ib_dma_mapping_error(priv->ca, addr))) {
+
+ if (unlikely(ipoib_dma_map_tx(priv->ca, tx_req))) {
++dev->stats.tx_errors;
dev_kfree_skb_any(skb);
return;
}
- tx_req->mapping = addr;
-
skb_orphan(skb);
skb_dst_drop(skb);
- rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),
- addr, skb->len);
+ rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), tx_req);
if (unlikely(rc)) {
ipoib_warn(priv, "post_send failed, error %d\n", rc);
++dev->stats.tx_errors;
- ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE);
+ ipoib_dma_unmap_tx(priv, tx_req);
dev_kfree_skb_any(skb);
} else {
dev->trans_start = jiffies;
@@ -777,7 +771,7 @@
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_cm_tx *tx = wc->qp->qp_context;
unsigned int wr_id = wc->wr_id & ~IPOIB_OP_CM;
- struct ipoib_cm_tx_buf *tx_req;
+ struct ipoib_tx_buf *tx_req;
unsigned long flags;
ipoib_dbg_data(priv, "cm send completion: id %d, status: %d\n",
@@ -791,7 +785,7 @@
tx_req = &tx->tx_ring[wr_id];
- ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len, DMA_TO_DEVICE);
+ ipoib_dma_unmap_tx(priv, tx_req);
/* FIXME: is this right? Shouldn't we only increment on success? */
++dev->stats.tx_packets;
@@ -1036,6 +1030,9 @@
struct ib_qp *tx_qp;
+ if (dev->features & NETIF_F_SG)
+ attr.cap.max_send_sge = MAX_SKB_FRAGS + 1;
+
tx_qp = ib_create_qp(priv->pd, &attr);
if (PTR_ERR(tx_qp) == -EINVAL) {
ipoib_warn(priv, "can't use GFP_NOIO for QPs on device %s, using GFP_KERNEL\n",
@@ -1170,7 +1167,7 @@
static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
{
struct ipoib_dev_priv *priv = netdev_priv(p->dev);
- struct ipoib_cm_tx_buf *tx_req;
+ struct ipoib_tx_buf *tx_req;
unsigned long begin;
ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n",
@@ -1197,8 +1194,7 @@
while ((int) p->tx_tail - (int) p->tx_head < 0) {
tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)];
- ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len,
- DMA_TO_DEVICE);
+ ipoib_dma_unmap_tx(priv, tx_req);
dev_kfree_skb_any(tx_req->skb);
++p->tx_tail;
netif_tx_lock_bh(p->dev);
@@ -1455,7 +1451,6 @@
spin_unlock_irq(&priv->lock);
}
-
static ssize_t show_mode(struct device *d, struct device_attribute *attr,
char *buf)
{
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 63b92cb..d266667 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -263,8 +263,7 @@
"for buf %d\n", wr_id);
}
-static int ipoib_dma_map_tx(struct ib_device *ca,
- struct ipoib_tx_buf *tx_req)
+int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req)
{
struct sk_buff *skb = tx_req->skb;
u64 *mapping = tx_req->mapping;
@@ -305,8 +304,8 @@
return -EIO;
}
-static void ipoib_dma_unmap_tx(struct ib_device *ca,
- struct ipoib_tx_buf *tx_req)
+void ipoib_dma_unmap_tx(struct ipoib_dev_priv *priv,
+ struct ipoib_tx_buf *tx_req)
{
struct sk_buff *skb = tx_req->skb;
u64 *mapping = tx_req->mapping;
@@ -314,7 +313,8 @@
int off;
if (skb_headlen(skb)) {
- ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
+ ib_dma_unmap_single(priv->ca, mapping[0], skb_headlen(skb),
+ DMA_TO_DEVICE);
off = 1;
} else
off = 0;
@@ -322,8 +322,8 @@
for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- ib_dma_unmap_page(ca, mapping[i + off], skb_frag_size(frag),
- DMA_TO_DEVICE);
+ ib_dma_unmap_page(priv->ca, mapping[i + off],
+ skb_frag_size(frag), DMA_TO_DEVICE);
}
}
@@ -389,7 +389,7 @@
tx_req = &priv->tx_ring[wr_id];
- ipoib_dma_unmap_tx(priv->ca, tx_req);
+ ipoib_dma_unmap_tx(priv, tx_req);
++dev->stats.tx_packets;
dev->stats.tx_bytes += tx_req->skb->len;
@@ -514,24 +514,10 @@
void *head, int hlen)
{
struct ib_send_wr *bad_wr;
- int i, off;
struct sk_buff *skb = tx_req->skb;
- skb_frag_t *frags = skb_shinfo(skb)->frags;
- int nr_frags = skb_shinfo(skb)->nr_frags;
- u64 *mapping = tx_req->mapping;
- if (skb_headlen(skb)) {
- priv->tx_sge[0].addr = mapping[0];
- priv->tx_sge[0].length = skb_headlen(skb);
- off = 1;
- } else
- off = 0;
+ ipoib_build_sge(priv, tx_req);
- for (i = 0; i < nr_frags; ++i) {
- priv->tx_sge[i + off].addr = mapping[i + off];
- priv->tx_sge[i + off].length = skb_frag_size(&frags[i]);
- }
- priv->tx_wr.num_sge = nr_frags + off;
priv->tx_wr.wr_id = wr_id;
priv->tx_wr.wr.ud.remote_qpn = qpn;
priv->tx_wr.wr.ud.ah = address;
@@ -617,7 +603,7 @@
ipoib_warn(priv, "post_send failed, error %d\n", rc);
++dev->stats.tx_errors;
--priv->tx_outstanding;
- ipoib_dma_unmap_tx(priv->ca, tx_req);
+ ipoib_dma_unmap_tx(priv, tx_req);
dev_kfree_skb_any(skb);
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
@@ -868,7 +854,7 @@
while ((int) priv->tx_tail - (int) priv->tx_head < 0) {
tx_req = &priv->tx_ring[priv->tx_tail &
(ipoib_sendq_size - 1)];
- ipoib_dma_unmap_tx(priv->ca, tx_req);
+ ipoib_dma_unmap_tx(priv, tx_req);
dev_kfree_skb_any(tx_req->skb);
++priv->tx_tail;
--priv->tx_outstanding;
@@ -985,20 +971,21 @@
}
static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
- enum ipoib_flush_level level)
+ enum ipoib_flush_level level,
+ int nesting)
{
struct ipoib_dev_priv *cpriv;
struct net_device *dev = priv->dev;
int result;
- down_read(&priv->vlan_rwsem);
+ down_read_nested(&priv->vlan_rwsem, nesting);
/*
* Flush any child interfaces too -- they might be up even if
* the parent is down.
*/
list_for_each_entry(cpriv, &priv->child_intfs, list)
- __ipoib_ib_dev_flush(cpriv, level);
+ __ipoib_ib_dev_flush(cpriv, level, nesting + 1);
up_read(&priv->vlan_rwsem);
@@ -1076,7 +1063,7 @@
struct ipoib_dev_priv *priv =
container_of(work, struct ipoib_dev_priv, flush_light);
- __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_LIGHT);
+ __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_LIGHT, 0);
}
void ipoib_ib_dev_flush_normal(struct work_struct *work)
@@ -1084,7 +1071,7 @@
struct ipoib_dev_priv *priv =
container_of(work, struct ipoib_dev_priv, flush_normal);
- __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_NORMAL);
+ __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_NORMAL, 0);
}
void ipoib_ib_dev_flush_heavy(struct work_struct *work)
@@ -1092,7 +1079,7 @@
struct ipoib_dev_priv *priv =
container_of(work, struct ipoib_dev_priv, flush_heavy);
- __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY);
+ __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY, 0);
}
void ipoib_ib_dev_cleanup(struct net_device *dev)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index da149c2..b2943c8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -190,7 +190,7 @@
struct ipoib_dev_priv *priv = netdev_priv(dev);
if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags))
- features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+ features &= ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
return features;
}
@@ -232,6 +232,7 @@
ipoib_warn(priv, "enabling connected mode "
"will cause multicast packet drops\n");
netdev_update_features(dev);
+ dev_set_mtu(dev, ipoib_cm_max_mtu(dev));
rtnl_unlock();
priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
@@ -1577,7 +1578,8 @@
SET_NETDEV_DEV(priv->dev, hca->dma_device);
priv->dev->dev_id = port - 1;
- if (!ib_query_port(hca, port, &attr))
+ result = ib_query_port(hca, port, &attr);
+ if (!result)
priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu);
else {
printk(KERN_WARNING "%s: ib_query_port %d failed\n",
@@ -1598,7 +1600,8 @@
goto device_init_failed;
}
- if (ipoib_set_dev_features(priv, hca))
+ result = ipoib_set_dev_features(priv, hca);
+ if (result)
goto device_init_failed;
/*
@@ -1684,7 +1687,7 @@
struct list_head *dev_list;
struct net_device *dev;
struct ipoib_dev_priv *priv;
- int s, e, p;
+ int p;
int count = 0;
dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
@@ -1693,15 +1696,7 @@
INIT_LIST_HEAD(dev_list);
- if (device->node_type == RDMA_NODE_IB_SWITCH) {
- s = 0;
- e = 0;
- } else {
- s = 1;
- e = device->phys_port_cnt;
- }
-
- for (p = s; p <= e; ++p) {
+ for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) {
if (!rdma_protocol_ib(device, p))
continue;
dev = ipoib_add_port("ib%d", device, p);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 267dc4f..31a20b4 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -161,13 +161,10 @@
{
int tmo, res;
- if (strncmp(val, "off", 3) != 0) {
- res = kstrtoint(val, 0, &tmo);
- if (res)
- goto out;
- } else {
- tmo = -1;
- }
+ res = srp_parse_tmo(&tmo, val);
+ if (res)
+ goto out;
+
if (kp->arg == &srp_reconnect_delay)
res = srp_tmo_valid(tmo, srp_fast_io_fail_tmo,
srp_dev_loss_tmo);
@@ -3379,7 +3376,7 @@
struct srp_device *srp_dev;
struct ib_device_attr *dev_attr;
struct srp_host *host;
- int mr_page_shift, s, e, p;
+ int mr_page_shift, p;
u64 max_pages_per_mr;
dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
@@ -3443,15 +3440,7 @@
if (IS_ERR(srp_dev->mr))
goto err_pd;
- if (device->node_type == RDMA_NODE_IB_SWITCH) {
- s = 0;
- e = 0;
- } else {
- s = 1;
- e = device->phys_port_cnt;
- }
-
- for (p = s; p <= e; ++p) {
+ for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) {
host = srp_add_port(srp_dev, p);
if (host)
list_add_tail(&host->list, &srp_dev->dev_list);
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 82897ca..60ff0a2 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -302,7 +302,7 @@
int i;
ioui = (struct ib_dm_iou_info *)mad->data;
- ioui->change_id = __constant_cpu_to_be16(1);
+ ioui->change_id = cpu_to_be16(1);
ioui->max_controllers = 16;
/* set present for slot 1 and empty for the rest */
@@ -330,13 +330,13 @@
if (!slot || slot > 16) {
mad->mad_hdr.status
- = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
+ = cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
return;
}
if (slot > 2) {
mad->mad_hdr.status
- = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
+ = cpu_to_be16(DM_MAD_STATUS_NO_IOC);
return;
}
@@ -348,10 +348,10 @@
iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver);
iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
iocp->subsys_device_id = 0x0;
- iocp->io_class = __constant_cpu_to_be16(SRP_REV16A_IB_IO_CLASS);
- iocp->io_subclass = __constant_cpu_to_be16(SRP_IO_SUBCLASS);
- iocp->protocol = __constant_cpu_to_be16(SRP_PROTOCOL);
- iocp->protocol_version = __constant_cpu_to_be16(SRP_PROTOCOL_VERSION);
+ iocp->io_class = cpu_to_be16(SRP_REV16A_IB_IO_CLASS);
+ iocp->io_subclass = cpu_to_be16(SRP_IO_SUBCLASS);
+ iocp->protocol = cpu_to_be16(SRP_PROTOCOL);
+ iocp->protocol_version = cpu_to_be16(SRP_PROTOCOL_VERSION);
iocp->send_queue_depth = cpu_to_be16(sdev->srq_size);
iocp->rdma_read_depth = 4;
iocp->send_size = cpu_to_be32(srp_max_req_size);
@@ -379,13 +379,13 @@
if (!slot || slot > 16) {
mad->mad_hdr.status
- = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
+ = cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
return;
}
if (slot > 2 || lo > hi || hi > 1) {
mad->mad_hdr.status
- = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
+ = cpu_to_be16(DM_MAD_STATUS_NO_IOC);
return;
}
@@ -436,7 +436,7 @@
break;
default:
rsp_mad->mad_hdr.status =
- __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
+ cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
break;
}
}
@@ -493,11 +493,11 @@
break;
case IB_MGMT_METHOD_SET:
dm_mad->mad_hdr.status =
- __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
+ cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
break;
default:
dm_mad->mad_hdr.status =
- __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD);
+ cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD);
break;
}
@@ -1535,7 +1535,7 @@
memset(srp_rsp, 0, sizeof *srp_rsp);
srp_rsp->opcode = SRP_RSP;
srp_rsp->req_lim_delta =
- __constant_cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0));
+ cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0));
srp_rsp->tag = tag;
srp_rsp->status = status;
@@ -1585,8 +1585,8 @@
memset(srp_rsp, 0, sizeof *srp_rsp);
srp_rsp->opcode = SRP_RSP;
- srp_rsp->req_lim_delta = __constant_cpu_to_be32(1
- + atomic_xchg(&ch->req_lim_delta, 0));
+ srp_rsp->req_lim_delta =
+ cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0));
srp_rsp->tag = tag;
srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
@@ -1630,7 +1630,7 @@
switch (len) {
case 8:
if ((*((__be64 *)lun) &
- __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0)
+ cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0)
goto out_err;
break;
case 4:
@@ -2449,8 +2449,8 @@
}
if (it_iu_len > srp_max_req_size || it_iu_len < 64) {
- rej->reason = __constant_cpu_to_be32(
- SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE);
+ rej->reason = cpu_to_be32(
+ SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE);
ret = -EINVAL;
pr_err("rejected SRP_LOGIN_REQ because its"
" length (%d bytes) is out of range (%d .. %d)\n",
@@ -2459,8 +2459,8 @@
}
if (!sport->enabled) {
- rej->reason = __constant_cpu_to_be32(
- SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ rej->reason = cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
ret = -EINVAL;
pr_err("rejected SRP_LOGIN_REQ because the target port"
" has not yet been enabled\n");
@@ -2505,8 +2505,8 @@
if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid)
|| *(__be64 *)(req->target_port_id + 8) !=
cpu_to_be64(srpt_service_guid)) {
- rej->reason = __constant_cpu_to_be32(
- SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL);
+ rej->reason = cpu_to_be32(
+ SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL);
ret = -ENOMEM;
pr_err("rejected SRP_LOGIN_REQ because it"
" has an invalid target port identifier.\n");
@@ -2515,8 +2515,8 @@
ch = kzalloc(sizeof *ch, GFP_KERNEL);
if (!ch) {
- rej->reason = __constant_cpu_to_be32(
- SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ rej->reason = cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
pr_err("rejected SRP_LOGIN_REQ because no memory.\n");
ret = -ENOMEM;
goto reject;
@@ -2552,8 +2552,8 @@
ret = srpt_create_ch_ib(ch);
if (ret) {
- rej->reason = __constant_cpu_to_be32(
- SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ rej->reason = cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
pr_err("rejected SRP_LOGIN_REQ because creating"
" a new RDMA channel failed.\n");
goto free_ring;
@@ -2561,8 +2561,7 @@
ret = srpt_ch_qp_rtr(ch, ch->qp);
if (ret) {
- rej->reason = __constant_cpu_to_be32(
- SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
pr_err("rejected SRP_LOGIN_REQ because enabling"
" RTR failed (error code = %d)\n", ret);
goto destroy_ib;
@@ -2580,15 +2579,15 @@
if (!nacl) {
pr_info("Rejected login because no ACL has been"
" configured yet for initiator %s.\n", ch->sess_name);
- rej->reason = __constant_cpu_to_be32(
- SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);
+ rej->reason = cpu_to_be32(
+ SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);
goto destroy_ib;
}
ch->sess = transport_init_session(TARGET_PROT_NORMAL);
if (IS_ERR(ch->sess)) {
- rej->reason = __constant_cpu_to_be32(
- SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ rej->reason = cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
pr_debug("Failed to create session\n");
goto deregister_session;
}
@@ -2604,8 +2603,8 @@
rsp->max_it_iu_len = req->req_it_iu_len;
rsp->max_ti_iu_len = req->req_it_iu_len;
ch->max_ti_iu_len = it_iu_len;
- rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
- | SRP_BUF_FORMAT_INDIRECT);
+ rsp->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT
+ | SRP_BUF_FORMAT_INDIRECT);
rsp->req_lim_delta = cpu_to_be32(ch->rq_size);
atomic_set(&ch->req_lim, ch->rq_size);
atomic_set(&ch->req_lim_delta, 0);
@@ -2655,8 +2654,8 @@
reject:
rej->opcode = SRP_LOGIN_REJ;
rej->tag = req->tag;
- rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
- | SRP_BUF_FORMAT_INDIRECT);
+ rej->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT
+ | SRP_BUF_FORMAT_INDIRECT);
ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
(void *)rej, sizeof *rej);
diff --git a/drivers/md/bcache/closure.h b/drivers/md/bcache/closure.h
index a08e3ee..79a6d63 100644
--- a/drivers/md/bcache/closure.h
+++ b/drivers/md/bcache/closure.h
@@ -320,7 +320,6 @@
do { \
set_closure_fn(_cl, _fn, _wq); \
closure_sub(_cl, CLOSURE_RUNNING + 1); \
- return; \
} while (0)
/**
@@ -349,7 +348,6 @@
do { \
set_closure_fn(_cl, _fn, _wq); \
closure_queue(_cl); \
- return; \
} while (0)
/**
@@ -365,7 +363,6 @@
do { \
set_closure_fn(_cl, _destructor, NULL); \
closure_sub(_cl, CLOSURE_RUNNING - CLOSURE_DESTRUCTOR + 1); \
- return; \
} while (0)
/**
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index cb64e64a..bf6a9ca 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -105,6 +105,7 @@
} while (n != bio);
continue_at(&s->cl, bch_bio_submit_split_done, NULL);
+ return;
submit:
generic_make_request(bio);
}
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index ce64fc8..418607a 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -592,12 +592,14 @@
if (!w->need_write) {
closure_return_with_destructor(cl, journal_write_unlock);
+ return;
} else if (journal_full(&c->journal)) {
journal_reclaim(c);
spin_unlock(&c->journal.lock);
btree_flush_write(c);
continue_at(cl, journal_write, system_wq);
+ return;
}
c->journal.blocks_free -= set_blocks(w->data, block_bytes(c));
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 4afb2d2..f292790 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -88,8 +88,10 @@
if (journal_ref)
atomic_dec_bug(journal_ref);
- if (!op->insert_data_done)
+ if (!op->insert_data_done) {
continue_at(cl, bch_data_insert_start, op->wq);
+ return;
+ }
bch_keylist_free(&op->insert_keys);
closure_return(cl);
@@ -216,8 +218,10 @@
/* 1 for the device pointer and 1 for the chksum */
if (bch_keylist_realloc(&op->insert_keys,
3 + (op->csum ? 1 : 0),
- op->c))
+ op->c)) {
continue_at(cl, bch_data_insert_keys, op->wq);
+ return;
+ }
k = op->insert_keys.top;
bkey_init(k);
@@ -255,6 +259,7 @@
op->insert_data_done = true;
continue_at(cl, bch_data_insert_keys, op->wq);
+ return;
err:
/* bch_alloc_sectors() blocks if s->writeback = true */
BUG_ON(op->writeback);
@@ -576,8 +581,10 @@
ret = bch_btree_map_keys(&s->op, s->iop.c,
&KEY(s->iop.inode, bio->bi_iter.bi_sector, 0),
cache_lookup_fn, MAP_END_KEY);
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN) {
continue_at(cl, cache_lookup, bcache_wq);
+ return;
+ }
closure_return(cl);
}
@@ -1085,6 +1092,7 @@
continue_at_nobarrier(&s->cl,
flash_dev_nodata,
bcache_wq);
+ return;
} else if (rw) {
bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys,
&KEY(d->id, bio->bi_iter.bi_sector, 0),
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 19eb990..317a494 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -689,40 +689,57 @@
}
-static bool bond_should_change_active(struct bonding *bond)
+static struct slave *bond_choose_primary_or_current(struct bonding *bond)
{
struct slave *prim = rtnl_dereference(bond->primary_slave);
struct slave *curr = rtnl_dereference(bond->curr_active_slave);
- if (!prim || !curr || curr->link != BOND_LINK_UP)
- return true;
+ if (!prim || prim->link != BOND_LINK_UP) {
+ if (!curr || curr->link != BOND_LINK_UP)
+ return NULL;
+ return curr;
+ }
+
if (bond->force_primary) {
bond->force_primary = false;
- return true;
+ return prim;
}
- if (bond->params.primary_reselect == BOND_PRI_RESELECT_BETTER &&
- (prim->speed < curr->speed ||
- (prim->speed == curr->speed && prim->duplex <= curr->duplex)))
- return false;
- if (bond->params.primary_reselect == BOND_PRI_RESELECT_FAILURE)
- return false;
- return true;
+
+ if (!curr || curr->link != BOND_LINK_UP)
+ return prim;
+
+ /* At this point, prim and curr are both up */
+ switch (bond->params.primary_reselect) {
+ case BOND_PRI_RESELECT_ALWAYS:
+ return prim;
+ case BOND_PRI_RESELECT_BETTER:
+ if (prim->speed < curr->speed)
+ return curr;
+ if (prim->speed == curr->speed && prim->duplex <= curr->duplex)
+ return curr;
+ return prim;
+ case BOND_PRI_RESELECT_FAILURE:
+ return curr;
+ default:
+ netdev_err(bond->dev, "impossible primary_reselect %d\n",
+ bond->params.primary_reselect);
+ return curr;
+ }
}
/**
- * find_best_interface - select the best available slave to be the active one
+ * bond_find_best_slave - select the best available slave to be the active one
* @bond: our bonding struct
*/
static struct slave *bond_find_best_slave(struct bonding *bond)
{
- struct slave *slave, *bestslave = NULL, *primary;
+ struct slave *slave, *bestslave = NULL;
struct list_head *iter;
int mintime = bond->params.updelay;
- primary = rtnl_dereference(bond->primary_slave);
- if (primary && primary->link == BOND_LINK_UP &&
- bond_should_change_active(bond))
- return primary;
+ slave = bond_choose_primary_or_current(bond);
+ if (slave)
+ return slave;
bond_for_each_slave(bond, slave, iter) {
if (slave->link == BOND_LINK_UP)
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 041525d..5d214d1 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -592,6 +592,7 @@
{
struct c_can_priv *priv = netdev_priv(dev);
int err;
+ struct pinctrl *p;
/* basic c_can configuration */
err = c_can_chip_config(dev);
@@ -604,8 +605,13 @@
priv->can.state = CAN_STATE_ERROR_ACTIVE;
- /* activate pins */
- pinctrl_pm_select_default_state(dev->dev.parent);
+ /* Attempt to use "active" if available else use "default" */
+ p = pinctrl_get_select(priv->device, "active");
+ if (!IS_ERR(p))
+ pinctrl_put(p);
+ else
+ pinctrl_pm_select_default_state(priv->device);
+
return 0;
}
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index e9b1810..aede704 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -440,9 +440,6 @@
struct can_frame *cf = (struct can_frame *)skb->data;
u8 dlc = cf->can_dlc;
- if (!(skb->tstamp.tv64))
- __net_timestamp(skb);
-
netif_rx(priv->echo_skb[idx]);
priv->echo_skb[idx] = NULL;
@@ -578,7 +575,6 @@
if (unlikely(!skb))
return NULL;
- __net_timestamp(skb);
skb->protocol = htons(ETH_P_CAN);
skb->pkt_type = PACKET_BROADCAST;
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -589,6 +585,7 @@
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
+ can_skb_prv(skb)->skbcnt = 0;
*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
memset(*cf, 0, sizeof(struct can_frame));
@@ -607,7 +604,6 @@
if (unlikely(!skb))
return NULL;
- __net_timestamp(skb);
skb->protocol = htons(ETH_P_CANFD);
skb->pkt_type = PACKET_BROADCAST;
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -618,6 +614,7 @@
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
+ can_skb_prv(skb)->skbcnt = 0;
*cfd = (struct canfd_frame *)skb_put(skb, sizeof(struct canfd_frame));
memset(*cfd, 0, sizeof(struct canfd_frame));
diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c
index 7deb80d..7bd5419 100644
--- a/drivers/net/can/rcar_can.c
+++ b/drivers/net/can/rcar_can.c
@@ -508,7 +508,8 @@
err = clk_prepare_enable(priv->clk);
if (err) {
- netdev_err(ndev, "failed to enable periperal clock, error %d\n",
+ netdev_err(ndev,
+ "failed to enable peripheral clock, error %d\n",
err);
goto out;
}
@@ -526,7 +527,8 @@
napi_enable(&priv->napi);
err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev);
if (err) {
- netdev_err(ndev, "error requesting interrupt %x\n", ndev->irq);
+ netdev_err(ndev, "request_irq(%d) failed, error %d\n",
+ ndev->irq, err);
goto out_close;
}
can_led_event(ndev, CAN_LED_EVENT_OPEN);
@@ -758,8 +760,9 @@
}
irq = platform_get_irq(pdev, 0);
- if (!irq) {
+ if (irq < 0) {
dev_err(&pdev->dev, "No IRQ resource\n");
+ err = irq;
goto fail;
}
@@ -782,7 +785,8 @@
priv->clk = devm_clk_get(&pdev->dev, "clkp1");
if (IS_ERR(priv->clk)) {
err = PTR_ERR(priv->clk);
- dev_err(&pdev->dev, "cannot get peripheral clock: %d\n", err);
+ dev_err(&pdev->dev, "cannot get peripheral clock, error %d\n",
+ err);
goto fail_clk;
}
@@ -794,7 +798,7 @@
priv->can_clk = devm_clk_get(&pdev->dev, clock_names[clock_select]);
if (IS_ERR(priv->can_clk)) {
err = PTR_ERR(priv->can_clk);
- dev_err(&pdev->dev, "cannot get CAN clock: %d\n", err);
+ dev_err(&pdev->dev, "cannot get CAN clock, error %d\n", err);
goto fail_clk;
}
@@ -823,7 +827,7 @@
devm_can_led_init(ndev);
- dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n",
+ dev_info(&pdev->dev, "device registered (regs @ %p, IRQ%d)\n",
priv->regs, ndev->irq);
return 0;
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index f64f529..a23a7af 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -207,7 +207,6 @@
if (!skb)
return;
- __net_timestamp(skb);
skb->dev = sl->dev;
skb->protocol = htons(ETH_P_CAN);
skb->pkt_type = PACKET_BROADCAST;
@@ -215,6 +214,7 @@
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = sl->dev->ifindex;
+ can_skb_prv(skb)->skbcnt = 0;
memcpy(skb_put(skb, sizeof(struct can_frame)),
&cf, sizeof(struct can_frame));
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index 0ce868d..674f367 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -78,9 +78,6 @@
skb->dev = dev;
skb->ip_summed = CHECKSUM_UNNECESSARY;
- if (!(skb->tstamp.tv64))
- __net_timestamp(skb);
-
netif_rx_ni(skb);
}
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 41095eb..2d1ce3c 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -2382,6 +2382,7 @@
void __iomem *ioaddr;
int status;
int work_done = max_interrupt_work;
+ int handled = 0;
ioaddr = vp->ioaddr;
@@ -2400,6 +2401,7 @@
if ((status & IntLatch) == 0)
goto handler_exit; /* No interrupt: shared IRQs can cause this */
+ handled = 1;
if (status == 0xffff) { /* h/w no longer present (hotplug)? */
if (vortex_debug > 1)
@@ -2501,7 +2503,7 @@
handler_exit:
vp->handling_irq = 0;
spin_unlock(&vp->lock);
- return IRQ_HANDLED;
+ return IRQ_RETVAL(handled);
}
static int vortex_rx(struct net_device *dev)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index 661cdaa..b3bc87f 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -303,7 +303,8 @@
get_page(pa->pages);
bd->pa = *pa;
- bd->dma = pa->pages_dma + pa->pages_offset;
+ bd->dma_base = pa->pages_dma;
+ bd->dma_off = pa->pages_offset;
bd->dma_len = len;
pa->pages_offset += len;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 506e832..a4473d8 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1110,6 +1110,7 @@
unsigned int rx_usecs = pdata->rx_usecs;
unsigned int rx_frames = pdata->rx_frames;
unsigned int inte;
+ dma_addr_t hdr_dma, buf_dma;
if (!rx_usecs && !rx_frames) {
/* No coalescing, interrupt for every descriptor */
@@ -1129,10 +1130,12 @@
* Set buffer 2 (hi) address to buffer dma address (hi) and
* set control bits OWN and INTE
*/
- rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx.hdr.dma));
- rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx.hdr.dma));
- rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma));
- rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma));
+ hdr_dma = rdata->rx.hdr.dma_base + rdata->rx.hdr.dma_off;
+ buf_dma = rdata->rx.buf.dma_base + rdata->rx.buf.dma_off;
+ rdesc->desc0 = cpu_to_le32(lower_32_bits(hdr_dma));
+ rdesc->desc1 = cpu_to_le32(upper_32_bits(hdr_dma));
+ rdesc->desc2 = cpu_to_le32(lower_32_bits(buf_dma));
+ rdesc->desc3 = cpu_to_le32(upper_32_bits(buf_dma));
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, inte);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 1e9c28d..aae9d5e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1765,8 +1765,9 @@
/* Start with the header buffer which may contain just the header
* or the header plus data
*/
- dma_sync_single_for_cpu(pdata->dev, rdata->rx.hdr.dma,
- rdata->rx.hdr.dma_len, DMA_FROM_DEVICE);
+ dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base,
+ rdata->rx.hdr.dma_off,
+ rdata->rx.hdr.dma_len, DMA_FROM_DEVICE);
packet = page_address(rdata->rx.hdr.pa.pages) +
rdata->rx.hdr.pa.pages_offset;
@@ -1778,8 +1779,11 @@
len -= copy_len;
if (len) {
/* Add the remaining data as a frag */
- dma_sync_single_for_cpu(pdata->dev, rdata->rx.buf.dma,
- rdata->rx.buf.dma_len, DMA_FROM_DEVICE);
+ dma_sync_single_range_for_cpu(pdata->dev,
+ rdata->rx.buf.dma_base,
+ rdata->rx.buf.dma_off,
+ rdata->rx.buf.dma_len,
+ DMA_FROM_DEVICE);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
rdata->rx.buf.pa.pages,
@@ -1945,8 +1949,9 @@
if (!skb)
error = 1;
} else if (rdesc_len) {
- dma_sync_single_for_cpu(pdata->dev,
- rdata->rx.buf.dma,
+ dma_sync_single_range_for_cpu(pdata->dev,
+ rdata->rx.buf.dma_base,
+ rdata->rx.buf.dma_off,
rdata->rx.buf.dma_len,
DMA_FROM_DEVICE);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 63d72a1..717ce21 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -337,7 +337,8 @@
struct xgbe_page_alloc pa;
struct xgbe_page_alloc pa_unmap;
- dma_addr_t dma;
+ dma_addr_t dma_base;
+ unsigned long dma_off;
unsigned int dma_len;
};
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 909ad7a..4566cdf 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -1793,7 +1793,7 @@
macaddr = of_get_mac_address(dn);
if (!macaddr || !is_valid_ether_addr(macaddr)) {
dev_warn(&pdev->dev, "using random Ethernet MAC\n");
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
} else {
ether_addr_copy(dev->dev_addr, macaddr);
}
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index b43b2cb..64c1e9d 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1230,7 +1230,6 @@
new_skb = skb_realloc_headroom(skb, sizeof(*status));
dev_kfree_skb(skb);
if (!new_skb) {
- dev->stats.tx_errors++;
dev->stats.tx_dropped++;
return NULL;
}
@@ -1465,7 +1464,6 @@
if (unlikely(!skb)) {
dev->stats.rx_dropped++;
- dev->stats.rx_errors++;
goto next;
}
@@ -1493,7 +1491,6 @@
if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
netif_err(priv, rx_status, dev,
"dropping fragmented packet!\n");
- dev->stats.rx_dropped++;
dev->stats.rx_errors++;
dev_kfree_skb_any(skb);
goto next;
@@ -1515,7 +1512,6 @@
dev->stats.rx_frame_errors++;
if (dma_flag & DMA_RX_LG)
dev->stats.rx_length_errors++;
- dev->stats.rx_dropped++;
dev->stats.rx_errors++;
dev_kfree_skb_any(skb);
goto next;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 484eb8c..a11485f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -952,16 +952,23 @@
* eventually have to put a format interpreter in here ...
*/
seq_printf(seq, "%10d %15llu %8s %8s ",
- e->seqno, e->timestamp,
+ be32_to_cpu(e->seqno),
+ be64_to_cpu(e->timestamp),
(e->level < ARRAY_SIZE(devlog_level_strings)
? devlog_level_strings[e->level]
: "UNKNOWN"),
(e->facility < ARRAY_SIZE(devlog_facility_strings)
? devlog_facility_strings[e->facility]
: "UNKNOWN"));
- seq_printf(seq, e->fmt, e->params[0], e->params[1],
- e->params[2], e->params[3], e->params[4],
- e->params[5], e->params[6], e->params[7]);
+ seq_printf(seq, e->fmt,
+ be32_to_cpu(e->params[0]),
+ be32_to_cpu(e->params[1]),
+ be32_to_cpu(e->params[2]),
+ be32_to_cpu(e->params[3]),
+ be32_to_cpu(e->params[4]),
+ be32_to_cpu(e->params[5]),
+ be32_to_cpu(e->params[6]),
+ be32_to_cpu(e->params[7]));
}
return 0;
}
@@ -1043,23 +1050,17 @@
return ret;
}
- /* Translate log multi-byte integral elements into host native format
- * and determine where the first entry in the log is.
+ /* Find the earliest (lowest Sequence Number) log entry in the
+ * circular Device Log.
*/
for (fseqno = ~((u32)0), index = 0; index < dinfo->nentries; index++) {
struct fw_devlog_e *e = &dinfo->log[index];
- int i;
__u32 seqno;
if (e->timestamp == 0)
continue;
- e->timestamp = (__force __be64)be64_to_cpu(e->timestamp);
seqno = be32_to_cpu(e->seqno);
- for (i = 0; i < 8; i++)
- e->params[i] =
- (__force __be32)be32_to_cpu(e->params[i]);
-
if (seqno < fseqno) {
fseqno = seqno;
dinfo->first = index;
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index da2004e..918a8e4 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1170,7 +1170,7 @@
wq_work_done,
0 /* dont unmask intr */,
0 /* dont reset intr timer */);
- return rq_work_done;
+ return budget;
}
if (budget > 0)
@@ -1191,6 +1191,7 @@
0 /* don't reset intr timer */);
err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
+ enic_poll_unlock_napi(&enic->rq[cq_rq], napi);
/* Buffer allocation failed. Stay in polling
* mode so we can try to fill the ring again.
@@ -1208,7 +1209,6 @@
napi_complete(napi);
vnic_intr_unmask(&enic->intr[intr]);
}
- enic_poll_unlock_napi(&enic->rq[cq_rq], napi);
return rq_work_done;
}
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1f89c59..42e20e5 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/pm_runtime.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
@@ -77,6 +78,7 @@
#define FEC_ENET_RAEM_V 0x8
#define FEC_ENET_RAFL_V 0x8
#define FEC_ENET_OPD_V 0xFFF0
+#define FEC_MDIO_PM_TIMEOUT 100 /* ms */
static struct platform_device_id fec_devtype[] = {
{
@@ -1767,7 +1769,13 @@
static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
struct fec_enet_private *fep = bus->priv;
+ struct device *dev = &fep->pdev->dev;
unsigned long time_left;
+ int ret = 0;
+
+ ret = pm_runtime_get_sync(dev);
+ if (IS_ERR_VALUE(ret))
+ return ret;
fep->mii_timeout = 0;
init_completion(&fep->mdio_done);
@@ -1783,18 +1791,30 @@
if (time_left == 0) {
fep->mii_timeout = 1;
netdev_err(fep->netdev, "MDIO read timeout\n");
- return -ETIMEDOUT;
+ ret = -ETIMEDOUT;
+ goto out;
}
- /* return value */
- return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
+ ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
+
+out:
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
}
static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
u16 value)
{
struct fec_enet_private *fep = bus->priv;
+ struct device *dev = &fep->pdev->dev;
unsigned long time_left;
+ int ret = 0;
+
+ ret = pm_runtime_get_sync(dev);
+ if (IS_ERR_VALUE(ret))
+ return ret;
fep->mii_timeout = 0;
init_completion(&fep->mdio_done);
@@ -1811,10 +1831,13 @@
if (time_left == 0) {
fep->mii_timeout = 1;
netdev_err(fep->netdev, "MDIO write timeout\n");
- return -ETIMEDOUT;
+ ret = -ETIMEDOUT;
}
- return 0;
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
}
static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
@@ -1826,9 +1849,6 @@
ret = clk_prepare_enable(fep->clk_ahb);
if (ret)
return ret;
- ret = clk_prepare_enable(fep->clk_ipg);
- if (ret)
- goto failed_clk_ipg;
if (fep->clk_enet_out) {
ret = clk_prepare_enable(fep->clk_enet_out);
if (ret)
@@ -1852,7 +1872,6 @@
}
} else {
clk_disable_unprepare(fep->clk_ahb);
- clk_disable_unprepare(fep->clk_ipg);
if (fep->clk_enet_out)
clk_disable_unprepare(fep->clk_enet_out);
if (fep->clk_ptp) {
@@ -1874,8 +1893,6 @@
if (fep->clk_enet_out)
clk_disable_unprepare(fep->clk_enet_out);
failed_clk_enet_out:
- clk_disable_unprepare(fep->clk_ipg);
-failed_clk_ipg:
clk_disable_unprepare(fep->clk_ahb);
return ret;
@@ -2847,10 +2864,14 @@
struct fec_enet_private *fep = netdev_priv(ndev);
int ret;
+ ret = pm_runtime_get_sync(&fep->pdev->dev);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
pinctrl_pm_select_default_state(&fep->pdev->dev);
ret = fec_enet_clk_enable(ndev, true);
if (ret)
- return ret;
+ goto clk_enable;
/* I should reset the ring buffers here, but I don't yet know
* a simple way to do that.
@@ -2881,6 +2902,9 @@
fec_enet_free_buffers(ndev);
err_enet_alloc:
fec_enet_clk_enable(ndev, false);
+clk_enable:
+ pm_runtime_mark_last_busy(&fep->pdev->dev);
+ pm_runtime_put_autosuspend(&fep->pdev->dev);
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
return ret;
}
@@ -2903,6 +2927,9 @@
fec_enet_clk_enable(ndev, false);
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+ pm_runtime_mark_last_busy(&fep->pdev->dev);
+ pm_runtime_put_autosuspend(&fep->pdev->dev);
+
fec_enet_free_buffers(ndev);
return 0;
@@ -3388,6 +3415,10 @@
if (ret)
goto failed_clk;
+ ret = clk_prepare_enable(fep->clk_ipg);
+ if (ret)
+ goto failed_clk_ipg;
+
fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
if (!IS_ERR(fep->reg_phy)) {
ret = regulator_enable(fep->reg_phy);
@@ -3434,6 +3465,8 @@
netif_carrier_off(ndev);
fec_enet_clk_enable(ndev, false);
pinctrl_pm_select_sleep_state(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
ret = register_netdev(ndev);
if (ret)
@@ -3447,6 +3480,12 @@
fep->rx_copybreak = COPYBREAK_DEFAULT;
INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+
return 0;
failed_register:
@@ -3457,6 +3496,8 @@
if (fep->reg_phy)
regulator_disable(fep->reg_phy);
failed_regulator:
+ clk_disable_unprepare(fep->clk_ipg);
+failed_clk_ipg:
fec_enet_clk_enable(ndev, false);
failed_clk:
failed_phy:
@@ -3568,7 +3609,28 @@
return ret;
}
-static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume);
+static int __maybe_unused fec_runtime_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct fec_enet_private *fep = netdev_priv(ndev);
+
+ clk_disable_unprepare(fep->clk_ipg);
+
+ return 0;
+}
+
+static int __maybe_unused fec_runtime_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct fec_enet_private *fep = netdev_priv(ndev);
+
+ return clk_prepare_enable(fep->clk_ipg);
+}
+
+static const struct dev_pm_ops fec_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume)
+ SET_RUNTIME_PM_OPS(fec_runtime_suspend, fec_runtime_resume, NULL)
+};
static struct platform_driver fec_driver = {
.driver = {
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 8476434..605cc89 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -101,6 +101,11 @@
return resource_size(&efx->pci_dev->resource[bar]);
}
+static bool efx_ef10_is_vf(struct efx_nic *efx)
+{
+ return efx->type->is_vf;
+}
+
static int efx_ef10_get_pf_index(struct efx_nic *efx)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN);
@@ -677,6 +682,48 @@
return efx_ef10_probe(efx);
}
+int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
+
+ MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
+ return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
+ NULL, 0, NULL);
+}
+
+int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
+
+ MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
+ return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
+ NULL, 0, NULL);
+}
+
+int efx_ef10_vport_add_mac(struct efx_nic *efx,
+ unsigned int port_id, u8 *mac)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
+
+ MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
+ ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
+
+ return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
+ sizeof(inbuf), NULL, 0, NULL);
+}
+
+int efx_ef10_vport_del_mac(struct efx_nic *efx,
+ unsigned int port_id, u8 *mac)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
+
+ MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
+ ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
+
+ return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
+ sizeof(inbuf), NULL, 0, NULL);
+}
+
#ifdef CONFIG_SFC_SRIOV
static int efx_ef10_probe_vf(struct efx_nic *efx)
{
@@ -3804,6 +3851,72 @@
WARN_ON(remove_failed);
}
+static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
+{
+ struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ u8 mac_old[ETH_ALEN];
+ int rc, rc2;
+
+ /* Only reconfigure a PF-created vport */
+ if (is_zero_ether_addr(nic_data->vport_mac))
+ return 0;
+
+ efx_device_detach_sync(efx);
+ efx_net_stop(efx->net_dev);
+ down_write(&efx->filter_sem);
+ efx_ef10_filter_table_remove(efx);
+ up_write(&efx->filter_sem);
+
+ rc = efx_ef10_vadaptor_free(efx, nic_data->vport_id);
+ if (rc)
+ goto restore_filters;
+
+ ether_addr_copy(mac_old, nic_data->vport_mac);
+ rc = efx_ef10_vport_del_mac(efx, nic_data->vport_id,
+ nic_data->vport_mac);
+ if (rc)
+ goto restore_vadaptor;
+
+ rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id,
+ efx->net_dev->dev_addr);
+ if (!rc) {
+ ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr);
+ } else {
+ rc2 = efx_ef10_vport_add_mac(efx, nic_data->vport_id, mac_old);
+ if (rc2) {
+ /* Failed to add original MAC, so clear vport_mac */
+ eth_zero_addr(nic_data->vport_mac);
+ goto reset_nic;
+ }
+ }
+
+restore_vadaptor:
+ rc2 = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
+ if (rc2)
+ goto reset_nic;
+restore_filters:
+ down_write(&efx->filter_sem);
+ rc2 = efx_ef10_filter_table_probe(efx);
+ up_write(&efx->filter_sem);
+ if (rc2)
+ goto reset_nic;
+
+ rc2 = efx_net_open(efx->net_dev);
+ if (rc2)
+ goto reset_nic;
+
+ netif_device_attach(efx->net_dev);
+
+ return rc;
+
+reset_nic:
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to restore when changing MAC address - scheduling reset\n");
+ efx_schedule_reset(efx, RESET_TYPE_DATAPATH);
+
+ return rc ? rc : rc2;
+}
+
static int efx_ef10_set_mac_address(struct efx_nic *efx)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
@@ -3820,8 +3933,8 @@
efx->net_dev->dev_addr);
MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
nic_data->vport_id);
- rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
- sizeof(inbuf), NULL, 0, NULL);
+ rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
+ sizeof(inbuf), NULL, 0, NULL);
efx_ef10_filter_table_probe(efx);
up_write(&efx->filter_sem);
@@ -3829,38 +3942,27 @@
efx_net_open(efx->net_dev);
netif_device_attach(efx->net_dev);
-#if !defined(CONFIG_SFC_SRIOV)
- if (rc == -EPERM)
- netif_err(efx, drv, efx->net_dev,
- "Cannot change MAC address; use sfboot to enable mac-spoofing"
- " on this interface\n");
-#else
- if (rc == -EPERM) {
+#ifdef CONFIG_SFC_SRIOV
+ if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) {
struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
- /* Switch to PF and change MAC address on vport */
- if (efx->pci_dev->is_virtfn && pci_dev_pf) {
- struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
+ if (rc == -EPERM) {
+ struct efx_nic *efx_pf;
- if (!efx_ef10_sriov_set_vf_mac(efx_pf,
+ /* Switch to PF and change MAC address on vport */
+ efx_pf = pci_get_drvdata(pci_dev_pf);
+
+ rc = efx_ef10_sriov_set_vf_mac(efx_pf,
nic_data->vf_index,
- efx->net_dev->dev_addr))
- return 0;
- }
- netif_err(efx, drv, efx->net_dev,
- "Cannot change MAC address; use sfboot to enable mac-spoofing"
- " on this interface\n");
- } else if (efx->pci_dev->is_virtfn) {
- /* Successfully changed by VF (with MAC spoofing), so update the
- * parent PF if possible.
- */
- struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
-
- if (pci_dev_pf) {
+ efx->net_dev->dev_addr);
+ } else if (!rc) {
struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
struct efx_ef10_nic_data *nic_data = efx_pf->nic_data;
unsigned int i;
+ /* MAC address successfully changed by VF (with MAC
+ * spoofing) so update the parent PF if possible.
+ */
for (i = 0; i < efx_pf->vf_count; ++i) {
struct ef10_vf *vf = nic_data->vf + i;
@@ -3871,8 +3973,24 @@
}
}
}
- }
+ } else
#endif
+ if (rc == -EPERM) {
+ netif_err(efx, drv, efx->net_dev,
+ "Cannot change MAC address; use sfboot to enable"
+ " mac-spoofing on this interface\n");
+ } else if (rc == -ENOSYS && !efx_ef10_is_vf(efx)) {
+ /* If the active MCFW does not support MC_CMD_VADAPTOR_SET_MAC
+ * fall-back to the method of changing the MAC address on the
+ * vport. This only applies to PFs because such versions of
+ * MCFW do not support VFs.
+ */
+ rc = efx_ef10_vport_set_mac_address(efx);
+ } else {
+ efx_mcdi_display_error(efx, MC_CMD_VADAPTOR_SET_MAC,
+ sizeof(inbuf), NULL, 0, rc);
+ }
+
return rc;
}
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c
index 6c9b6e4..3c17f27 100644
--- a/drivers/net/ethernet/sfc/ef10_sriov.c
+++ b/drivers/net/ethernet/sfc/ef10_sriov.c
@@ -29,30 +29,6 @@
NULL, 0, NULL);
}
-static int efx_ef10_vport_add_mac(struct efx_nic *efx,
- unsigned int port_id, u8 *mac)
-{
- MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
-
- MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
- ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
-
- return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
- sizeof(inbuf), NULL, 0, NULL);
-}
-
-static int efx_ef10_vport_del_mac(struct efx_nic *efx,
- unsigned int port_id, u8 *mac)
-{
- MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
-
- MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
- ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
-
- return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
- sizeof(inbuf), NULL, 0, NULL);
-}
-
static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
unsigned int vswitch_type)
{
@@ -136,24 +112,6 @@
NULL, 0, NULL);
}
-static int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
-{
- MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
-
- MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
- return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
- NULL, 0, NULL);
-}
-
-static int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
-{
- MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
-
- MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
- return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
- NULL, 0, NULL);
-}
-
static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
@@ -640,21 +598,21 @@
MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
vf->vlan, &vf->vport_id);
if (rc)
- goto reset_nic;
+ goto reset_nic_up_write;
restore_mac:
if (!is_zero_ether_addr(vf->mac)) {
rc2 = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac);
if (rc2) {
eth_zero_addr(vf->mac);
- goto reset_nic;
+ goto reset_nic_up_write;
}
}
restore_evb_port:
rc2 = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i);
if (rc2)
- goto reset_nic;
+ goto reset_nic_up_write;
else
vf->vport_assigned = 1;
@@ -662,14 +620,16 @@
if (vf->efx) {
rc2 = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED);
if (rc2)
- goto reset_nic;
+ goto reset_nic_up_write;
}
restore_filters:
if (vf->efx) {
rc2 = vf->efx->type->filter_table_probe(vf->efx);
if (rc2)
- goto reset_nic;
+ goto reset_nic_up_write;
+
+ up_write(&vf->efx->filter_sem);
up_write(&vf->efx->filter_sem);
@@ -681,9 +641,12 @@
}
return rc;
+reset_nic_up_write:
+ if (vf->efx)
+ up_write(&vf->efx->filter_sem);
+
reset_nic:
if (vf->efx) {
- up_write(&vf->efx->filter_sem);
netif_err(efx, drv, efx->net_dev,
"Failed to restore VF - scheduling reset.\n");
efx_schedule_reset(vf->efx, RESET_TYPE_DATAPATH);
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.h b/drivers/net/ethernet/sfc/ef10_sriov.h
index db4ef53..6d25b92 100644
--- a/drivers/net/ethernet/sfc/ef10_sriov.h
+++ b/drivers/net/ethernet/sfc/ef10_sriov.h
@@ -65,5 +65,11 @@
int efx_ef10_vswitching_restore_vf(struct efx_nic *efx);
void efx_ef10_vswitching_remove_pf(struct efx_nic *efx);
void efx_ef10_vswitching_remove_vf(struct efx_nic *efx);
+int efx_ef10_vport_add_mac(struct efx_nic *efx,
+ unsigned int port_id, u8 *mac);
+int efx_ef10_vport_del_mac(struct efx_nic *efx,
+ unsigned int port_id, u8 *mac);
+int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id);
+int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id);
#endif /* EF10_SRIOV_H */
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 804b9ad..03bc03b 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -245,11 +245,17 @@
*/
static int efx_process_channel(struct efx_channel *channel, int budget)
{
+ struct efx_tx_queue *tx_queue;
int spent;
if (unlikely(!channel->enabled))
return 0;
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ tx_queue->pkts_compl = 0;
+ tx_queue->bytes_compl = 0;
+ }
+
spent = efx_nic_process_eventq(channel, budget);
if (spent && efx_channel_has_rx_queue(channel)) {
struct efx_rx_queue *rx_queue =
@@ -259,6 +265,14 @@
efx_fast_push_rx_descriptors(rx_queue, true);
}
+ /* Update BQL */
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ if (tx_queue->bytes_compl) {
+ netdev_tx_completed_queue(tx_queue->core_txq,
+ tx_queue->pkts_compl, tx_queue->bytes_compl);
+ }
+ }
+
return spent;
}
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index d72f522..47d1e3a 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -241,6 +241,8 @@
unsigned int read_count ____cacheline_aligned_in_smp;
unsigned int old_write_count;
unsigned int merge_events;
+ unsigned int bytes_compl;
+ unsigned int pkts_compl;
/* Members used only on the xmit path */
unsigned int insert_count ____cacheline_aligned_in_smp;
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index aaf2987..1833a01 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -617,7 +617,8 @@
EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask);
efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl);
- netdev_tx_completed_queue(tx_queue->core_txq, pkts_compl, bytes_compl);
+ tx_queue->pkts_compl += pkts_compl;
+ tx_queue->bytes_compl += bytes_compl;
if (pkts_compl > 1)
++tx_queue->merge_events;
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 4628205..f335bf1 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -138,19 +138,6 @@
#define CPSW_CMINTMAX_INTVL (1000 / CPSW_CMINTMIN_CNT)
#define CPSW_CMINTMIN_INTVL ((1000 / CPSW_CMINTMAX_CNT) + 1)
-#define cpsw_enable_irq(priv) \
- do { \
- u32 i; \
- for (i = 0; i < priv->num_irqs; i++) \
- enable_irq(priv->irqs_table[i]); \
- } while (0)
-#define cpsw_disable_irq(priv) \
- do { \
- u32 i; \
- for (i = 0; i < priv->num_irqs; i++) \
- disable_irq_nosync(priv->irqs_table[i]); \
- } while (0)
-
#define cpsw_slave_index(priv) \
((priv->data.dual_emac) ? priv->emac_port : \
priv->data.active_slave)
@@ -509,9 +496,11 @@
(func)(slave++, ##arg); \
} while (0)
#define cpsw_get_slave_ndev(priv, __slave_no__) \
- (priv->slaves[__slave_no__].ndev)
+ ((__slave_no__ < priv->data.slaves) ? \
+ priv->slaves[__slave_no__].ndev : NULL)
#define cpsw_get_slave_priv(priv, __slave_no__) \
- ((priv->slaves[__slave_no__].ndev) ? \
+ (((__slave_no__ < priv->data.slaves) && \
+ (priv->slaves[__slave_no__].ndev)) ? \
netdev_priv(priv->slaves[__slave_no__].ndev) : NULL) \
#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb) \
@@ -781,7 +770,7 @@
cpsw_intr_disable(priv);
if (priv->irq_enabled == true) {
- cpsw_disable_irq(priv);
+ disable_irq_nosync(priv->irqs_table[0]);
priv->irq_enabled = false;
}
@@ -817,7 +806,7 @@
prim_cpsw = cpsw_get_slave_priv(priv, 0);
if (prim_cpsw->irq_enabled == false) {
prim_cpsw->irq_enabled = true;
- cpsw_enable_irq(priv);
+ enable_irq(priv->irqs_table[0]);
}
}
@@ -1333,7 +1322,7 @@
if (prim_cpsw->irq_enabled == false) {
if ((priv == prim_cpsw) || !netif_running(prim_cpsw->ndev)) {
prim_cpsw->irq_enabled = true;
- cpsw_enable_irq(prim_cpsw);
+ enable_irq(prim_cpsw->irqs_table[0]);
}
}
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 4208dd7..d95f9aa 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1530,9 +1530,9 @@
/* Map device registers */
ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
- if (!lp->regs) {
+ if (IS_ERR(lp->regs)) {
dev_err(&pdev->dev, "could not map Axi Ethernet regs.\n");
- ret = -ENOMEM;
+ ret = PTR_ERR(lp->regs);
goto free_netdev;
}
@@ -1599,9 +1599,9 @@
goto free_netdev;
}
lp->dma_regs = devm_ioremap_resource(&pdev->dev, &dmares);
- if (!lp->dma_regs) {
+ if (IS_ERR(lp->dma_regs)) {
dev_err(&pdev->dev, "could not map DMA regs\n");
- ret = -ENOMEM;
+ ret = PTR_ERR(lp->dma_regs);
goto free_netdev;
}
lp->rx_irq = irq_of_parse_and_map(np, 1);
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 7856b6c..d95a50a 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -482,6 +482,7 @@
memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
dev->flags = 0;
+ dev->features = NETIF_F_LLTX; /* Allow recursion */
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
dev->header_ops = &ax25_header_ops;
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index f837080..3b933bb 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -1355,6 +1355,7 @@
class_unregister(macvtap_class);
cdev_del(&macvtap_cdev);
unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
+ idr_destroy(&minor_idr);
}
module_exit(macvtap_exit);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index cf18940..cb86d7a 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -191,7 +191,7 @@
config MDIO_BUS_MUX_MMIOREG
tristate "Support for MMIO device-controlled MDIO bus multiplexers"
- depends on OF_MDIO
+ depends on OF_MDIO && HAS_IOMEM
select MDIO_BUS_MUX
help
This module provides a driver for MDIO bus multiplexers that
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 4545e78..35a2bff 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -523,6 +523,7 @@
#define REALTEK_VENDOR_ID 0x0bda
#define SAMSUNG_VENDOR_ID 0x04e8
#define LENOVO_VENDOR_ID 0x17ef
+#define NVIDIA_VENDOR_ID 0x0955
static const struct usb_device_id products[] = {
/* BLACKLIST !!
@@ -710,6 +711,13 @@
.driver_info = 0,
},
+/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
/* WHITELIST!!!
*
* CDC Ether uses two interfaces, not necessarily consecutive.
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index e4b7a47..efc18e0 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -158,7 +158,7 @@
if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
goto err;
- ret = cdc_ncm_bind_common(dev, intf, data_altsetting);
+ ret = cdc_ncm_bind_common(dev, intf, data_altsetting, 0);
if (ret)
goto err;
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 8067b8f..db40175 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -6,7 +6,7 @@
* Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
*
* USB Host Driver for Network Control Model (NCM)
- * http://www.usb.org/developers/devclass_docs/NCM10.zip
+ * http://www.usb.org/developers/docs/devclass_docs/NCM10_012011.zip
*
* The NCM encoding, decoding and initialization logic
* derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
@@ -684,10 +684,12 @@
ctx->tx_curr_skb = NULL;
}
+ kfree(ctx->delayed_ndp16);
+
kfree(ctx);
}
-int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
+int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags)
{
const struct usb_cdc_union_desc *union_desc = NULL;
struct cdc_ncm_ctx *ctx;
@@ -855,6 +857,17 @@
/* finish setting up the device specific data */
cdc_ncm_setup(dev);
+ /* Device-specific flags */
+ ctx->drvflags = drvflags;
+
+ /* Allocate the delayed NDP if needed. */
+ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
+ ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
+ if (!ctx->delayed_ndp16)
+ goto error2;
+ dev_info(&intf->dev, "NDP will be placed at end of frame for this device.");
+ }
+
/* override ethtool_ops */
dev->net->ethtool_ops = &cdc_ncm_ethtool_ops;
@@ -954,8 +967,11 @@
if (cdc_ncm_select_altsetting(intf) != CDC_NCM_COMM_ALTSETTING_NCM)
return -ENODEV;
- /* The NCM data altsetting is fixed */
- ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM);
+ /* The NCM data altsetting is fixed, so we hard-coded it.
+ * Additionally, generic NCM devices are assumed to accept arbitrarily
+ * placed NDP.
+ */
+ ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM, 0);
/*
* We should get an event when network connection is "connected" or
@@ -986,6 +1002,14 @@
struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);
+ /* If NDP should be moved to the end of the NCM package, we can't follow the
+ * NTH16 header as we would normally do. NDP isn't written to the SKB yet, and
+ * the wNdpIndex field in the header is actually not consistent with reality. It will be later.
+ */
+ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
+ if (ctx->delayed_ndp16->dwSignature == sign)
+ return ctx->delayed_ndp16;
+
/* follow the chain of NDPs, looking for a match */
while (ndpoffset) {
ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
@@ -995,7 +1019,8 @@
}
/* align new NDP */
- cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
+ if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
+ cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
/* verify that there is room for the NDP and the datagram (reserve) */
if ((ctx->tx_max - skb->len - reserve) < ctx->max_ndp_size)
@@ -1008,7 +1033,11 @@
nth16->wNdpIndex = cpu_to_le16(skb->len);
/* push a new empty NDP */
- ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size);
+ if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
+ ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size);
+ else
+ ndp16 = ctx->delayed_ndp16;
+
ndp16->dwSignature = sign;
ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16));
return ndp16;
@@ -1023,6 +1052,15 @@
struct sk_buff *skb_out;
u16 n = 0, index, ndplen;
u8 ready2send = 0;
+ u32 delayed_ndp_size;
+
+ /* When our NDP gets written in cdc_ncm_ndp(), then skb_out->len gets updated
+ * accordingly. Otherwise, we should check here.
+ */
+ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
+ delayed_ndp_size = ctx->max_ndp_size;
+ else
+ delayed_ndp_size = 0;
/* if there is a remaining skb, it gets priority */
if (skb != NULL) {
@@ -1077,7 +1115,7 @@
cdc_ncm_align_tail(skb_out, ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max);
/* check if we had enough room left for both NDP and frame */
- if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) {
+ if (!ndp16 || skb_out->len + skb->len + delayed_ndp_size > ctx->tx_max) {
if (n == 0) {
/* won't fit, MTU problem? */
dev_kfree_skb_any(skb);
@@ -1150,6 +1188,17 @@
/* variables will be reset at next call */
}
+ /* If requested, put NDP at end of frame. */
+ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
+ nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+ cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_max);
+ nth16->wNdpIndex = cpu_to_le16(skb_out->len);
+ memcpy(skb_put(skb_out, ctx->max_ndp_size), ctx->delayed_ndp16, ctx->max_ndp_size);
+
+ /* Zero out delayed NDP - signature checking will naturally fail. */
+ ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size);
+ }
+
/* If collected data size is less or equal ctx->min_tx_pkt
* bytes, we send buffers as it is. If we get more data, it
* would be more efficient for USB HS mobile device with DMA
diff --git a/drivers/net/usb/huawei_cdc_ncm.c b/drivers/net/usb/huawei_cdc_ncm.c
index 735f7da..2680a65 100644
--- a/drivers/net/usb/huawei_cdc_ncm.c
+++ b/drivers/net/usb/huawei_cdc_ncm.c
@@ -73,11 +73,14 @@
struct usb_driver *subdriver = ERR_PTR(-ENODEV);
int ret = -ENODEV;
struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
+ int drvflags = 0;
/* altsetting should always be 1 for NCM devices - so we hard-coded
- * it here
+ * it here. Some huawei devices will need the NDP part of the NCM package to
+ * be at the end of the frame.
*/
- ret = cdc_ncm_bind_common(usbnet_dev, intf, 1);
+ drvflags |= CDC_NCM_FLAG_NDP_TO_END;
+ ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags);
if (ret)
goto err;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index aafa1a1..7f6419e 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -494,6 +494,7 @@
#define VENDOR_ID_REALTEK 0x0bda
#define VENDOR_ID_SAMSUNG 0x04e8
#define VENDOR_ID_LENOVO 0x17ef
+#define VENDOR_ID_NVIDIA 0x0955
#define MCU_TYPE_PLA 0x0100
#define MCU_TYPE_USB 0x0000
@@ -4117,6 +4118,7 @@
{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)},
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)},
+ {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)},
{}
};
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index da11bb5..46f4cad 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1216,7 +1216,7 @@
static const u32 rxprod_reg[2] = {
VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2
};
- u32 num_rxd = 0;
+ u32 num_pkts = 0;
bool skip_page_frags = false;
struct Vmxnet3_RxCompDesc *rcd;
struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
@@ -1235,13 +1235,12 @@
struct Vmxnet3_RxDesc *rxd;
u32 idx, ring_idx;
struct vmxnet3_cmd_ring *ring = NULL;
- if (num_rxd >= quota) {
+ if (num_pkts >= quota) {
/* we may stop even before we see the EOP desc of
* the current pkt
*/
break;
}
- num_rxd++;
BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2);
idx = rcd->rxdIdx;
ring_idx = rcd->rqID < adapter->num_rx_queues ? 0 : 1;
@@ -1413,6 +1412,7 @@
napi_gro_receive(&rq->napi, skb);
ctx->skb = NULL;
+ num_pkts++;
}
rcd_done:
@@ -1443,7 +1443,7 @@
&rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
}
- return num_rxd;
+ return num_pkts;
}
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index feacc3b..2f0bd69 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -1044,7 +1044,7 @@
* @dev: The network device to attach
* @c: The Z8530 channel to configure in sync DMA mode.
*
- * Set up a Z85x30 device for synchronous DMA tranmission. One
+ * Set up a Z85x30 device for synchronous DMA transmission. One
* ISA DMA channel must be available for this to work. The receive
* side is run in PIO mode, but then it has the bigger FIFO.
*/
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index ed317cc..aaeeae8 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -309,12 +309,15 @@
static struct calling_interface_buffer *buffer;
static DEFINE_MUTEX(buffer_mutex);
-static int hwswitch_state;
+static void clear_buffer(void)
+{
+ memset(buffer, 0, sizeof(struct calling_interface_buffer));
+}
static void get_buffer(void)
{
mutex_lock(&buffer_mutex);
- memset(buffer, 0, sizeof(struct calling_interface_buffer));
+ clear_buffer();
}
static void release_buffer(void)
@@ -548,21 +551,41 @@
int disable = blocked ? 1 : 0;
unsigned long radio = (unsigned long)data;
int hwswitch_bit = (unsigned long)data - 1;
+ int hwswitch;
+ int status;
+ int ret;
get_buffer();
+
dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
+ status = buffer->output[1];
+
+ if (ret != 0)
+ goto out;
+
+ clear_buffer();
+
+ buffer->input[0] = 0x2;
+ dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
+ hwswitch = buffer->output[1];
/* If the hardware switch controls this radio, and the hardware
switch is disabled, always disable the radio */
- if ((hwswitch_state & BIT(hwswitch_bit)) &&
- !(buffer->output[1] & BIT(16)))
+ if (ret == 0 && (hwswitch & BIT(hwswitch_bit)) &&
+ (status & BIT(0)) && !(status & BIT(16)))
disable = 1;
+ clear_buffer();
+
buffer->input[0] = (1 | (radio<<8) | (disable << 16));
dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
+ out:
release_buffer();
- return 0;
+ return dell_smi_error(ret);
}
/* Must be called with the buffer held */
@@ -572,6 +595,7 @@
if (status & BIT(0)) {
/* Has hw-switch, sync sw_state to BIOS */
int block = rfkill_blocked(rfkill);
+ clear_buffer();
buffer->input[0] = (1 | (radio << 8) | (block << 16));
dell_send_request(buffer, 17, 11);
} else {
@@ -581,23 +605,43 @@
}
static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio,
- int status)
+ int status, int hwswitch)
{
- if (hwswitch_state & (BIT(radio - 1)))
+ if (hwswitch & (BIT(radio - 1)))
rfkill_set_hw_state(rfkill, !(status & BIT(16)));
}
static void dell_rfkill_query(struct rfkill *rfkill, void *data)
{
+ int radio = ((unsigned long)data & 0xF);
+ int hwswitch;
int status;
+ int ret;
get_buffer();
+
dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
status = buffer->output[1];
- dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status);
+ if (ret != 0 || !(status & BIT(0))) {
+ release_buffer();
+ return;
+ }
+
+ clear_buffer();
+
+ buffer->input[0] = 0x2;
+ dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
+ hwswitch = buffer->output[1];
release_buffer();
+
+ if (ret != 0)
+ return;
+
+ dell_rfkill_update_hw_state(rfkill, radio, status, hwswitch);
}
static const struct rfkill_ops dell_rfkill_ops = {
@@ -609,13 +653,27 @@
static int dell_debugfs_show(struct seq_file *s, void *data)
{
+ int hwswitch_state;
+ int hwswitch_ret;
int status;
+ int ret;
get_buffer();
+
dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
status = buffer->output[1];
+
+ clear_buffer();
+
+ buffer->input[0] = 0x2;
+ dell_send_request(buffer, 17, 11);
+ hwswitch_ret = buffer->output[0];
+ hwswitch_state = buffer->output[1];
+
release_buffer();
+ seq_printf(s, "return:\t%d\n", ret);
seq_printf(s, "status:\t0x%X\n", status);
seq_printf(s, "Bit 0 : Hardware switch supported: %lu\n",
status & BIT(0));
@@ -657,7 +715,8 @@
seq_printf(s, "Bit 21: WiGig is blocked: %lu\n",
(status & BIT(21)) >> 21);
- seq_printf(s, "\nhwswitch_state:\t0x%X\n", hwswitch_state);
+ seq_printf(s, "\nhwswitch_return:\t%d\n", hwswitch_ret);
+ seq_printf(s, "hwswitch_state:\t0x%X\n", hwswitch_state);
seq_printf(s, "Bit 0 : Wifi controlled by switch: %lu\n",
hwswitch_state & BIT(0));
seq_printf(s, "Bit 1 : Bluetooth controlled by switch: %lu\n",
@@ -693,25 +752,43 @@
static void dell_update_rfkill(struct work_struct *ignored)
{
+ int hwswitch = 0;
int status;
+ int ret;
get_buffer();
+
dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
status = buffer->output[1];
+ if (ret != 0)
+ goto out;
+
+ clear_buffer();
+
+ buffer->input[0] = 0x2;
+ dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
+
+ if (ret == 0 && (status & BIT(0)))
+ hwswitch = buffer->output[1];
+
if (wifi_rfkill) {
- dell_rfkill_update_hw_state(wifi_rfkill, 1, status);
+ dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch);
dell_rfkill_update_sw_state(wifi_rfkill, 1, status);
}
if (bluetooth_rfkill) {
- dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status);
+ dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status,
+ hwswitch);
dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status);
}
if (wwan_rfkill) {
- dell_rfkill_update_hw_state(wwan_rfkill, 3, status);
+ dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch);
dell_rfkill_update_sw_state(wwan_rfkill, 3, status);
}
+ out:
release_buffer();
}
static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
@@ -773,21 +850,17 @@
get_buffer();
dell_send_request(buffer, 17, 11);
+ ret = buffer->output[0];
status = buffer->output[1];
- buffer->input[0] = 0x2;
- dell_send_request(buffer, 17, 11);
- hwswitch_state = buffer->output[1];
release_buffer();
- if (!(status & BIT(0))) {
- if (force_rfkill) {
- /* No hwsitch, clear all hw-controlled bits */
- hwswitch_state &= ~7;
- } else {
- /* rfkill is only tested on laptops with a hwswitch */
- return 0;
- }
- }
+ /* dell wireless info smbios call is not supported */
+ if (ret != 0)
+ return 0;
+
+ /* rfkill is only tested on laptops with a hwswitch */
+ if (!(status & BIT(0)) && !force_rfkill)
+ return 0;
if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
@@ -932,47 +1005,50 @@
static int dell_send_intensity(struct backlight_device *bd)
{
- int ret = 0;
+ int token;
+ int ret;
+
+ token = find_token_location(BRIGHTNESS_TOKEN);
+ if (token == -1)
+ return -ENODEV;
get_buffer();
- buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
+ buffer->input[0] = token;
buffer->input[1] = bd->props.brightness;
- if (buffer->input[0] == -1) {
- ret = -ENODEV;
- goto out;
- }
-
if (power_supply_is_system_supplied() > 0)
dell_send_request(buffer, 1, 2);
else
dell_send_request(buffer, 1, 1);
- out:
+ ret = dell_smi_error(buffer->output[0]);
+
release_buffer();
return ret;
}
static int dell_get_intensity(struct backlight_device *bd)
{
- int ret = 0;
+ int token;
+ int ret;
+
+ token = find_token_location(BRIGHTNESS_TOKEN);
+ if (token == -1)
+ return -ENODEV;
get_buffer();
- buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
-
- if (buffer->input[0] == -1) {
- ret = -ENODEV;
- goto out;
- }
+ buffer->input[0] = token;
if (power_supply_is_system_supplied() > 0)
dell_send_request(buffer, 0, 2);
else
dell_send_request(buffer, 0, 1);
- ret = buffer->output[1];
+ if (buffer->output[0])
+ ret = dell_smi_error(buffer->output[0]);
+ else
+ ret = buffer->output[1];
- out:
release_buffer();
return ret;
}
@@ -2036,6 +2112,7 @@
static int __init dell_init(void)
{
int max_intensity = 0;
+ int token;
int ret;
if (!dmi_check_system(dell_device_table))
@@ -2094,13 +2171,15 @@
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
return 0;
- get_buffer();
- buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN);
- if (buffer->input[0] != -1) {
+ token = find_token_location(BRIGHTNESS_TOKEN);
+ if (token != -1) {
+ get_buffer();
+ buffer->input[0] = token;
dell_send_request(buffer, 0, 2);
- max_intensity = buffer->output[3];
+ if (buffer->output[0] == 0)
+ max_intensity = buffer->output[3];
+ release_buffer();
}
- release_buffer();
if (max_intensity) {
struct backlight_properties props;
diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c
index d734763..105cfff 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -96,18 +96,18 @@
struct completion cmd_complete;
/* The following PMC BARs share the same ACPI device with the IPC */
- void *acpi_io_base;
+ resource_size_t acpi_io_base;
int acpi_io_size;
struct platform_device *tco_dev;
/* gcr */
- void *gcr_base;
+ resource_size_t gcr_base;
int gcr_size;
/* punit */
- void *punit_base;
+ resource_size_t punit_base;
int punit_size;
- void *punit_base2;
+ resource_size_t punit_base2;
int punit_size2;
struct platform_device *punit_dev;
} ipcdev;
@@ -210,10 +210,15 @@
return ret;
}
-/*
- * intel_pmc_ipc_simple_command
- * @cmd: command
- * @sub: sub type
+/**
+ * intel_pmc_ipc_simple_command() - Simple IPC command
+ * @cmd: IPC command code.
+ * @sub: IPC command sub type.
+ *
+ * Send a simple IPC command to PMC when don't need to specify
+ * input/output data and source/dest pointers.
+ *
+ * Return: an IPC error code or 0 on success.
*/
int intel_pmc_ipc_simple_command(int cmd, int sub)
{
@@ -232,16 +237,20 @@
}
EXPORT_SYMBOL_GPL(intel_pmc_ipc_simple_command);
-/*
- * intel_pmc_ipc_raw_cmd
- * @cmd: command
- * @sub: sub type
- * @in: input data
- * @inlen: input length in bytes
- * @out: output data
- * @outlen: output length in dwords
- * @sptr: data writing to SPTR register
- * @dptr: data writing to DPTR register
+/**
+ * intel_pmc_ipc_raw_cmd() - IPC command with data and pointers
+ * @cmd: IPC command code.
+ * @sub: IPC command sub type.
+ * @in: input data of this IPC command.
+ * @inlen: input data length in bytes.
+ * @out: output data of this IPC command.
+ * @outlen: output data length in dwords.
+ * @sptr: data writing to SPTR register.
+ * @dptr: data writing to DPTR register.
+ *
+ * Send an IPC command to PMC with input/output data and source/dest pointers.
+ *
+ * Return: an IPC error code or 0 on success.
*/
int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out,
u32 outlen, u32 dptr, u32 sptr)
@@ -278,14 +287,18 @@
}
EXPORT_SYMBOL_GPL(intel_pmc_ipc_raw_cmd);
-/*
- * intel_pmc_ipc_command
- * @cmd: command
- * @sub: sub type
- * @in: input data
- * @inlen: input length in bytes
- * @out: output data
- * @outlen: output length in dwords
+/**
+ * intel_pmc_ipc_command() - IPC command with input/output data
+ * @cmd: IPC command code.
+ * @sub: IPC command sub type.
+ * @in: input data of this IPC command.
+ * @inlen: input data length in bytes.
+ * @out: output data of this IPC command.
+ * @outlen: output data length in dwords.
+ *
+ * Send an IPC command to PMC with input/output data.
+ *
+ * Return: an IPC error code or 0 on success.
*/
int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
u32 *out, u32 outlen)
@@ -480,11 +493,11 @@
pdev->dev.parent = ipcdev.dev;
res = punit_res;
- res->start = (resource_size_t)ipcdev.punit_base;
+ res->start = ipcdev.punit_base;
res->end = res->start + ipcdev.punit_size - 1;
res = punit_res + PUNIT_RESOURCE_INTER;
- res->start = (resource_size_t)ipcdev.punit_base2;
+ res->start = ipcdev.punit_base2;
res->end = res->start + ipcdev.punit_size2 - 1;
ret = platform_device_add_resources(pdev, punit_res,
@@ -522,15 +535,15 @@
pdev->dev.parent = ipcdev.dev;
res = tco_res + TCO_RESOURCE_ACPI_IO;
- res->start = (resource_size_t)ipcdev.acpi_io_base + TCO_BASE_OFFSET;
+ res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET;
res->end = res->start + TCO_REGS_SIZE - 1;
res = tco_res + TCO_RESOURCE_SMI_EN_IO;
- res->start = (resource_size_t)ipcdev.acpi_io_base + SMI_EN_OFFSET;
+ res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET;
res->end = res->start + SMI_EN_SIZE - 1;
res = tco_res + TCO_RESOURCE_GCR_MEM;
- res->start = (resource_size_t)ipcdev.gcr_base;
+ res->start = ipcdev.gcr_base;
res->end = res->start + ipcdev.gcr_size - 1;
ret = platform_device_add_resources(pdev, tco_res, ARRAY_SIZE(tco_res));
@@ -589,7 +602,7 @@
return -ENXIO;
}
size = resource_size(res);
- ipcdev.acpi_io_base = (void *)res->start;
+ ipcdev.acpi_io_base = res->start;
ipcdev.acpi_io_size = size;
dev_info(&pdev->dev, "io res: %llx %x\n",
(long long)res->start, (int)resource_size(res));
@@ -601,7 +614,7 @@
return -ENXIO;
}
size = resource_size(res);
- ipcdev.punit_base = (void *)res->start;
+ ipcdev.punit_base = res->start;
ipcdev.punit_size = size;
dev_info(&pdev->dev, "punit data res: %llx %x\n",
(long long)res->start, (int)resource_size(res));
@@ -613,7 +626,7 @@
return -ENXIO;
}
size = resource_size(res);
- ipcdev.punit_base2 = (void *)res->start;
+ ipcdev.punit_base2 = res->start;
ipcdev.punit_size2 = size;
dev_info(&pdev->dev, "punit interface res: %llx %x\n",
(long long)res->start, (int)resource_size(res));
@@ -637,7 +650,7 @@
}
ipcdev.ipc_base = addr;
- ipcdev.gcr_base = (void *)(res->start + size);
+ ipcdev.gcr_base = res->start + size;
ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE;
dev_info(&pdev->dev, "ipc res: %llx %x\n",
(long long)res->start, (int)resource_size(res));
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 001b199..187d108 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -216,13 +216,13 @@
int nc;
u32 offset = 0;
int err;
- u8 cbuf[IPC_WWBUF_SIZE] = { };
+ u8 cbuf[IPC_WWBUF_SIZE];
u32 *wbuf = (u32 *)&cbuf;
- mutex_lock(&ipclock);
-
memset(cbuf, 0, sizeof(cbuf));
+ mutex_lock(&ipclock);
+
if (ipcdev.pdev == NULL) {
mutex_unlock(&ipclock);
return -ENODEV;
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 1aec8ff..f73d2f5 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1863,6 +1863,33 @@
}
/*
+ * return 1 when device is not eligible for IO
+ */
+static int __dasd_device_is_unusable(struct dasd_device *device,
+ struct dasd_ccw_req *cqr)
+{
+ int mask = ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM);
+
+ if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
+ /* dasd is being set offline. */
+ return 1;
+ }
+ if (device->stopped) {
+ if (device->stopped & mask) {
+ /* stopped and CQR will not change that. */
+ return 1;
+ }
+ if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
+ /* CQR is not able to change device to
+ * operational. */
+ return 1;
+ }
+ /* CQR required to get device operational. */
+ }
+ return 0;
+}
+
+/*
* Take a look at the first request on the ccw queue and check
* if it needs to be started.
*/
@@ -1876,13 +1903,8 @@
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist);
if (cqr->status != DASD_CQR_QUEUED)
return;
- /* when device is stopped, return request to previous layer
- * exception: only the disconnect or unresumed bits are set and the
- * cqr is a path verification request
- */
- if (device->stopped &&
- !(!(device->stopped & ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM))
- && test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))) {
+ /* if device is not usable return request to upper layer */
+ if (__dasd_device_is_unusable(device, cqr)) {
cqr->intrc = -EAGAIN;
cqr->status = DASD_CQR_CLEARED;
dasd_schedule_device_bh(device);
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index a2597e6..ee3a6fa 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -699,7 +699,8 @@
struct dasd_device, alias_list);
spin_unlock_irqrestore(&lcu->lock, flags);
alias_priv = (struct dasd_eckd_private *) alias_device->private;
- if ((alias_priv->count < private->count) && !alias_device->stopped)
+ if ((alias_priv->count < private->count) && !alias_device->stopped &&
+ !test_bit(DASD_FLAG_OFFLINE, &alias_device->flags))
return alias_device;
else
return NULL;
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index aeed796..7bc6df3 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -7,6 +7,7 @@
#define KMSG_COMPONENT "sclp_early"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#include <linux/errno.h>
#include <asm/ctl_reg.h>
#include <asm/sclp.h>
#include <asm/ipl.h>
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 08f1830..01bf1f5 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -54,6 +54,10 @@
"Copyright IBM Corp. 2001, 2012");
MODULE_LICENSE("GPL");
+static int zcrypt_hwrng_seed = 1;
+module_param_named(hwrng_seed, zcrypt_hwrng_seed, int, S_IRUSR|S_IRGRP);
+MODULE_PARM_DESC(hwrng_seed, "Turn on/off hwrng auto seed, default is 1 (on).");
+
static DEFINE_SPINLOCK(zcrypt_device_lock);
static LIST_HEAD(zcrypt_device_list);
static int zcrypt_device_count = 0;
@@ -1373,6 +1377,7 @@
static struct hwrng zcrypt_rng_dev = {
.name = "zcrypt",
.data_read = zcrypt_rng_data_read,
+ .quality = 990,
};
static int zcrypt_rng_device_add(void)
@@ -1387,6 +1392,8 @@
goto out;
}
zcrypt_rng_buffer_index = 0;
+ if (!zcrypt_hwrng_seed)
+ zcrypt_rng_dev.quality = 0;
rc = hwrng_register(&zcrypt_rng_dev);
if (rc)
goto out_free;
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
index a85292b..e3cd3ec 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -203,7 +203,7 @@
return tmo >= 0 ? sprintf(buf, "%d\n", tmo) : sprintf(buf, "off\n");
}
-static int srp_parse_tmo(int *tmo, const char *buf)
+int srp_parse_tmo(int *tmo, const char *buf)
{
int res = 0;
@@ -214,6 +214,7 @@
return res;
}
+EXPORT_SYMBOL(srp_parse_tmo);
static ssize_t show_reconnect_delay(struct device *dev,
struct device_attribute *attr, char *buf)
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index e98d39d..b9dc23c 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -76,7 +76,7 @@
if (ji->active_ag == -1) {
struct jfs_sb_info *jfs_sb = JFS_SBI(inode->i_sb);
ji->active_ag = BLKTOAG(addressPXD(&ji->ixpxd), jfs_sb);
- atomic_inc( &jfs_sb->bmap->db_active[ji->active_ag]);
+ atomic_inc(&jfs_sb->bmap->db_active[ji->active_ag]);
}
spin_unlock_irq(&ji->ag_lock);
}
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 6f1cb2b..41aa3ca 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -134,11 +134,11 @@
* It has been committed since the last change, but was still
* on the dirty inode list.
*/
- if (!test_cflag(COMMIT_Dirty, inode)) {
+ if (!test_cflag(COMMIT_Dirty, inode)) {
/* Make sure committed changes hit the disk */
jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait);
return 0;
- }
+ }
if (jfs_commit_inode(inode, wait)) {
jfs_err("jfs_write_inode: jfs_commit_inode failed!");
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index e33be92..a5ac97b 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1160,7 +1160,7 @@
rc = dtModify(tid, new_dir, &new_dname, &ino,
old_ip->i_ino, JFS_RENAME);
if (rc)
- goto out4;
+ goto out_tx;
drop_nlink(new_ip);
if (S_ISDIR(new_ip->i_mode)) {
drop_nlink(new_ip);
@@ -1185,7 +1185,7 @@
if ((new_size = commitZeroLink(tid, new_ip)) < 0) {
txAbort(tid, 1); /* Marks FS Dirty */
rc = new_size;
- goto out4;
+ goto out_tx;
}
tblk = tid_to_tblock(tid);
tblk->xflag |= COMMIT_DELETE;
@@ -1203,7 +1203,7 @@
if (rc) {
jfs_err("jfs_rename didn't expect dtSearch to fail "
"w/rc = %d", rc);
- goto out4;
+ goto out_tx;
}
ino = old_ip->i_ino;
@@ -1211,7 +1211,7 @@
if (rc) {
if (rc == -EIO)
jfs_err("jfs_rename: dtInsert returned -EIO");
- goto out4;
+ goto out_tx;
}
if (S_ISDIR(old_ip->i_mode))
inc_nlink(new_dir);
@@ -1226,7 +1226,7 @@
jfs_err("jfs_rename did not expect dtDelete to return rc = %d",
rc);
txAbort(tid, 1); /* Marks Filesystem dirty */
- goto out4;
+ goto out_tx;
}
if (S_ISDIR(old_ip->i_mode)) {
drop_nlink(old_dir);
@@ -1285,7 +1285,7 @@
rc = txCommit(tid, ipcount, iplist, commit_flag);
- out4:
+ out_tx:
txEnd(tid);
if (new_ip)
mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
@@ -1308,13 +1308,6 @@
}
if (new_ip && (new_ip->i_nlink == 0))
set_cflag(COMMIT_Nolink, new_ip);
- out3:
- free_UCSname(&new_dname);
- out2:
- free_UCSname(&old_dname);
- out1:
- if (new_ip && !S_ISDIR(new_ip->i_mode))
- IWRITE_UNLOCK(new_ip);
/*
* Truncating the directory index table is not guaranteed. It
* may need to be done iteratively
@@ -1325,7 +1318,13 @@
clear_cflag(COMMIT_Stale, old_dir);
}
-
+ if (new_ip && !S_ISDIR(new_ip->i_mode))
+ IWRITE_UNLOCK(new_ip);
+ out3:
+ free_UCSname(&new_dname);
+ out2:
+ free_UCSname(&old_dname);
+ out1:
jfs_info("jfs_rename: returning %d", rc);
return rc;
}
diff --git a/fs/locks.c b/fs/locks.c
index 653faab..d3d558b 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -862,12 +862,11 @@
* whether or not a lock was successfully freed by testing the return
* value for -ENOENT.
*/
-static int flock_lock_file(struct file *filp, struct file_lock *request)
+static int flock_lock_inode(struct inode *inode, struct file_lock *request)
{
struct file_lock *new_fl = NULL;
struct file_lock *fl;
struct file_lock_context *ctx;
- struct inode *inode = file_inode(filp);
int error = 0;
bool found = false;
LIST_HEAD(dispose);
@@ -890,7 +889,7 @@
goto find_conflict;
list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
- if (filp != fl->fl_file)
+ if (request->fl_file != fl->fl_file)
continue;
if (request->fl_type == fl->fl_type)
goto out;
@@ -1164,20 +1163,19 @@
EXPORT_SYMBOL(posix_lock_file);
/**
- * posix_lock_file_wait - Apply a POSIX-style lock to a file
- * @filp: The file to apply the lock to
+ * posix_lock_inode_wait - Apply a POSIX-style lock to a file
+ * @inode: inode of file to which lock request should be applied
* @fl: The lock to be applied
*
- * Add a POSIX style lock to a file.
- * We merge adjacent & overlapping locks whenever possible.
- * POSIX locks are sorted by owner task, then by starting address
+ * Variant of posix_lock_file_wait that does not take a filp, and so can be
+ * used after the filp has already been torn down.
*/
-int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
+int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
{
int error;
might_sleep ();
for (;;) {
- error = posix_lock_file(filp, fl, NULL);
+ error = __posix_lock_file(inode, fl, NULL);
if (error != FILE_LOCK_DEFERRED)
break;
error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
@@ -1189,7 +1187,7 @@
}
return error;
}
-EXPORT_SYMBOL(posix_lock_file_wait);
+EXPORT_SYMBOL(posix_lock_inode_wait);
/**
* locks_mandatory_locked - Check for an active lock
@@ -1851,18 +1849,18 @@
}
/**
- * flock_lock_file_wait - Apply a FLOCK-style lock to a file
- * @filp: The file to apply the lock to
+ * flock_lock_inode_wait - Apply a FLOCK-style lock to a file
+ * @inode: inode of the file to apply to
* @fl: The lock to be applied
*
- * Add a FLOCK style lock to a file.
+ * Apply a FLOCK style lock request to an inode.
*/
-int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
+int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl)
{
int error;
might_sleep();
for (;;) {
- error = flock_lock_file(filp, fl);
+ error = flock_lock_inode(inode, fl);
if (error != FILE_LOCK_DEFERRED)
break;
error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
@@ -1874,8 +1872,7 @@
}
return error;
}
-
-EXPORT_SYMBOL(flock_lock_file_wait);
+EXPORT_SYMBOL(flock_lock_inode_wait);
/**
* sys_flock: - flock() system call.
@@ -2401,7 +2398,8 @@
.fl_type = F_UNLCK,
.fl_end = OFFSET_MAX,
};
- struct file_lock_context *flctx = file_inode(filp)->i_flctx;
+ struct inode *inode = file_inode(filp);
+ struct file_lock_context *flctx = inode->i_flctx;
if (list_empty(&flctx->flc_flock))
return;
@@ -2409,7 +2407,7 @@
if (filp->f_op->flock)
filp->f_op->flock(filp, F_SETLKW, &fl);
else
- flock_lock_file(filp, &fl);
+ flock_lock_inode(inode, &fl);
if (fl.fl_ops && fl.fl_ops->fl_release_private)
fl.fl_ops->fl_release_private(&fl);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6f228b5..8bee934 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5439,15 +5439,15 @@
return err;
}
-static int do_vfs_lock(struct file *file, struct file_lock *fl)
+static int do_vfs_lock(struct inode *inode, struct file_lock *fl)
{
int res = 0;
switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
case FL_POSIX:
- res = posix_lock_file_wait(file, fl);
+ res = posix_lock_inode_wait(inode, fl);
break;
case FL_FLOCK:
- res = flock_lock_file_wait(file, fl);
+ res = flock_lock_inode_wait(inode, fl);
break;
default:
BUG();
@@ -5484,7 +5484,6 @@
atomic_inc(&lsp->ls_count);
/* Ensure we don't close file until we're done freeing locks! */
p->ctx = get_nfs_open_context(ctx);
- get_file(fl->fl_file);
memcpy(&p->fl, fl, sizeof(p->fl));
p->server = NFS_SERVER(inode);
return p;
@@ -5496,7 +5495,6 @@
nfs_free_seqid(calldata->arg.seqid);
nfs4_put_lock_state(calldata->lsp);
put_nfs_open_context(calldata->ctx);
- fput(calldata->fl.fl_file);
kfree(calldata);
}
@@ -5509,7 +5507,7 @@
switch (task->tk_status) {
case 0:
renew_lease(calldata->server, calldata->timestamp);
- do_vfs_lock(calldata->fl.fl_file, &calldata->fl);
+ do_vfs_lock(calldata->lsp->ls_state->inode, &calldata->fl);
if (nfs4_update_lock_stateid(calldata->lsp,
&calldata->res.stateid))
break;
@@ -5617,7 +5615,7 @@
mutex_lock(&sp->so_delegreturn_mutex);
/* Exclude nfs4_reclaim_open_stateid() - note nesting! */
down_read(&nfsi->rwsem);
- if (do_vfs_lock(request->fl_file, request) == -ENOENT) {
+ if (do_vfs_lock(inode, request) == -ENOENT) {
up_read(&nfsi->rwsem);
mutex_unlock(&sp->so_delegreturn_mutex);
goto out;
@@ -5758,7 +5756,7 @@
data->timestamp);
if (data->arg.new_lock) {
data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);
- if (do_vfs_lock(data->fl.fl_file, &data->fl) < 0) {
+ if (do_vfs_lock(lsp->ls_state->inode, &data->fl) < 0) {
rpc_restart_call_prepare(task);
break;
}
@@ -6000,7 +5998,7 @@
if (status != 0)
goto out;
request->fl_flags |= FL_ACCESS;
- status = do_vfs_lock(request->fl_file, request);
+ status = do_vfs_lock(state->inode, request);
if (status < 0)
goto out;
down_read(&nfsi->rwsem);
@@ -6008,7 +6006,7 @@
/* Yes: cache locks! */
/* ...but avoid races with delegation recall... */
request->fl_flags = fl_flags & ~FL_SLEEP;
- status = do_vfs_lock(request->fl_file, request);
+ status = do_vfs_lock(state->inode, request);
up_read(&nfsi->rwsem);
goto out;
}
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index 58cfab8..1b62d76 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -47,6 +47,7 @@
struct blkcg_policy_data *pd[BLKCG_MAX_POLS];
+ struct list_head all_blkcgs_node;
#ifdef CONFIG_CGROUP_WRITEBACK
struct list_head cgwb_list;
#endif
@@ -88,18 +89,12 @@
* Policies that need to keep per-blkcg data which is independent
* from any request_queue associated to it must specify its size
* with the cpd_size field of the blkcg_policy structure and
- * embed a blkcg_policy_data in it. blkcg core allocates
- * policy-specific per-blkcg structures lazily the first time
- * they are actually needed, so it handles them together with
- * blkgs. cpd_init() is invoked to let each policy handle
- * per-blkcg data.
+ * embed a blkcg_policy_data in it. cpd_init() is invoked to let
+ * each policy handle per-blkcg data.
*/
struct blkcg_policy_data {
/* the policy id this per-policy data belongs to */
int plid;
-
- /* used during policy activation */
- struct list_head alloc_node;
};
/* association between a blk cgroup and a request queue */
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index b6a52a4..51bb653 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -27,10 +27,12 @@
/**
* struct can_skb_priv - private additional data inside CAN sk_buffs
* @ifindex: ifindex of the first interface the CAN frame appeared on
+ * @skbcnt: atomic counter to have an unique id together with skb pointer
* @cf: align to the following CAN frame at skb->data
*/
struct can_skb_priv {
int ifindex;
+ int skbcnt;
struct can_frame cf[0];
};
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a0653e5..cc008c3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1046,12 +1046,12 @@
extern void locks_release_private(struct file_lock *);
extern void posix_test_lock(struct file *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
-extern int posix_lock_file_wait(struct file *, struct file_lock *);
+extern int posix_lock_inode_wait(struct inode *, struct file_lock *);
extern int posix_unblock_lock(struct file_lock *);
extern int vfs_test_lock(struct file *, struct file_lock *);
extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
-extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
+extern int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl);
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
extern void lease_get_mtime(struct inode *, struct timespec *time);
extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
@@ -1137,7 +1137,8 @@
return -ENOLCK;
}
-static inline int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
+static inline int posix_lock_inode_wait(struct inode *inode,
+ struct file_lock *fl)
{
return -ENOLCK;
}
@@ -1163,8 +1164,8 @@
return 0;
}
-static inline int flock_lock_file_wait(struct file *filp,
- struct file_lock *request)
+static inline int flock_lock_inode_wait(struct inode *inode,
+ struct file_lock *request)
{
return -ENOLCK;
}
@@ -1202,6 +1203,20 @@
struct file *filp, struct files_struct *files) {}
#endif /* !CONFIG_FILE_LOCKING */
+static inline struct inode *file_inode(const struct file *f)
+{
+ return f->f_inode;
+}
+
+static inline int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
+{
+ return posix_lock_inode_wait(file_inode(filp), fl);
+}
+
+static inline int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
+{
+ return flock_lock_inode_wait(file_inode(filp), fl);
+}
struct fasync_struct {
spinlock_t fa_lock;
@@ -2011,11 +2026,6 @@
extern void iput(struct inode *);
extern int generic_update_time(struct inode *, struct timespec *, int);
-static inline struct inode *file_inode(const struct file *f)
-{
- return f->f_inode;
-}
-
/* /sys/fs */
extern struct kobject *fs_kobj;
diff --git a/include/linux/init.h b/include/linux/init.h
index 7c68c36..b449f37 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -282,68 +282,8 @@
void __init parse_early_options(char *cmdline);
#endif /* __ASSEMBLY__ */
-/**
- * module_init() - driver initialization entry point
- * @x: function to be run at kernel boot time or module insertion
- *
- * module_init() will either be called during do_initcalls() (if
- * builtin) or at module insertion time (if a module). There can only
- * be one per module.
- */
-#define module_init(x) __initcall(x);
-
-/**
- * module_exit() - driver exit entry point
- * @x: function to be run when driver is removed
- *
- * module_exit() will wrap the driver clean-up code
- * with cleanup_module() when used with rmmod when
- * the driver is a module. If the driver is statically
- * compiled into the kernel, module_exit() has no effect.
- * There can only be one per module.
- */
-#define module_exit(x) __exitcall(x);
-
#else /* MODULE */
-/*
- * In most cases loadable modules do not need custom
- * initcall levels. There are still some valid cases where
- * a driver may be needed early if built in, and does not
- * matter when built as a loadable module. Like bus
- * snooping debug drivers.
- */
-#define early_initcall(fn) module_init(fn)
-#define core_initcall(fn) module_init(fn)
-#define core_initcall_sync(fn) module_init(fn)
-#define postcore_initcall(fn) module_init(fn)
-#define postcore_initcall_sync(fn) module_init(fn)
-#define arch_initcall(fn) module_init(fn)
-#define subsys_initcall(fn) module_init(fn)
-#define subsys_initcall_sync(fn) module_init(fn)
-#define fs_initcall(fn) module_init(fn)
-#define fs_initcall_sync(fn) module_init(fn)
-#define rootfs_initcall(fn) module_init(fn)
-#define device_initcall(fn) module_init(fn)
-#define device_initcall_sync(fn) module_init(fn)
-#define late_initcall(fn) module_init(fn)
-#define late_initcall_sync(fn) module_init(fn)
-
-#define console_initcall(fn) module_init(fn)
-#define security_initcall(fn) module_init(fn)
-
-/* Each module must use one module_init(). */
-#define module_init(initfn) \
- static inline initcall_t __inittest(void) \
- { return initfn; } \
- int init_module(void) __attribute__((alias(#initfn)));
-
-/* This is only required if you want to be unloadable. */
-#define module_exit(exitfn) \
- static inline exitcall_t __exittest(void) \
- { return exitfn; } \
- void cleanup_module(void) __attribute__((alias(#exitfn)));
-
#define __setup_param(str, unique_id, fn) /* nothing */
#define __setup(str, func) /* nothing */
#endif
@@ -351,24 +291,6 @@
/* Data marked not to be saved by software suspend */
#define __nosavedata __section(.data..nosave)
-/* This means "can be init if no module support, otherwise module load
- may call it." */
-#ifdef CONFIG_MODULES
-#define __init_or_module
-#define __initdata_or_module
-#define __initconst_or_module
-#define __INIT_OR_MODULE .text
-#define __INITDATA_OR_MODULE .data
-#define __INITRODATA_OR_MODULE .section ".rodata","a",%progbits
-#else
-#define __init_or_module __init
-#define __initdata_or_module __initdata
-#define __initconst_or_module __initconst
-#define __INIT_OR_MODULE __INIT
-#define __INITDATA_OR_MODULE __INITDATA
-#define __INITRODATA_OR_MODULE __INITRODATA
-#endif /*CONFIG_MODULES*/
-
#ifdef MODULE
#define __exit_p(x) x
#else
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 9564fd7..05e99b8 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -734,6 +734,24 @@
return false;
}
#endif
+#ifdef __KVM_HAVE_ARCH_ASSIGNED_DEVICE
+void kvm_arch_start_assignment(struct kvm *kvm);
+void kvm_arch_end_assignment(struct kvm *kvm);
+bool kvm_arch_has_assigned_device(struct kvm *kvm);
+#else
+static inline void kvm_arch_start_assignment(struct kvm *kvm)
+{
+}
+
+static inline void kvm_arch_end_assignment(struct kvm *kvm)
+{
+}
+
+static inline bool kvm_arch_has_assigned_device(struct kvm *kvm)
+{
+ return false;
+}
+#endif
static inline wait_queue_head_t *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
{
diff --git a/include/linux/module.h b/include/linux/module.h
index d67b193..3a19c79 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -11,6 +11,7 @@
#include <linux/compiler.h>
#include <linux/cache.h>
#include <linux/kmod.h>
+#include <linux/init.h>
#include <linux/elf.h>
#include <linux/stringify.h>
#include <linux/kobject.h>
@@ -71,6 +72,89 @@
extern int init_module(void);
extern void cleanup_module(void);
+#ifndef MODULE
+/**
+ * module_init() - driver initialization entry point
+ * @x: function to be run at kernel boot time or module insertion
+ *
+ * module_init() will either be called during do_initcalls() (if
+ * builtin) or at module insertion time (if a module). There can only
+ * be one per module.
+ */
+#define module_init(x) __initcall(x);
+
+/**
+ * module_exit() - driver exit entry point
+ * @x: function to be run when driver is removed
+ *
+ * module_exit() will wrap the driver clean-up code
+ * with cleanup_module() when used with rmmod when
+ * the driver is a module. If the driver is statically
+ * compiled into the kernel, module_exit() has no effect.
+ * There can only be one per module.
+ */
+#define module_exit(x) __exitcall(x);
+
+#else /* MODULE */
+
+/*
+ * In most cases loadable modules do not need custom
+ * initcall levels. There are still some valid cases where
+ * a driver may be needed early if built in, and does not
+ * matter when built as a loadable module. Like bus
+ * snooping debug drivers.
+ */
+#define early_initcall(fn) module_init(fn)
+#define core_initcall(fn) module_init(fn)
+#define core_initcall_sync(fn) module_init(fn)
+#define postcore_initcall(fn) module_init(fn)
+#define postcore_initcall_sync(fn) module_init(fn)
+#define arch_initcall(fn) module_init(fn)
+#define subsys_initcall(fn) module_init(fn)
+#define subsys_initcall_sync(fn) module_init(fn)
+#define fs_initcall(fn) module_init(fn)
+#define fs_initcall_sync(fn) module_init(fn)
+#define rootfs_initcall(fn) module_init(fn)
+#define device_initcall(fn) module_init(fn)
+#define device_initcall_sync(fn) module_init(fn)
+#define late_initcall(fn) module_init(fn)
+#define late_initcall_sync(fn) module_init(fn)
+
+#define console_initcall(fn) module_init(fn)
+#define security_initcall(fn) module_init(fn)
+
+/* Each module must use one module_init(). */
+#define module_init(initfn) \
+ static inline initcall_t __inittest(void) \
+ { return initfn; } \
+ int init_module(void) __attribute__((alias(#initfn)));
+
+/* This is only required if you want to be unloadable. */
+#define module_exit(exitfn) \
+ static inline exitcall_t __exittest(void) \
+ { return exitfn; } \
+ void cleanup_module(void) __attribute__((alias(#exitfn)));
+
+#endif
+
+/* This means "can be init if no module support, otherwise module load
+ may call it." */
+#ifdef CONFIG_MODULES
+#define __init_or_module
+#define __initdata_or_module
+#define __initconst_or_module
+#define __INIT_OR_MODULE .text
+#define __INITDATA_OR_MODULE .data
+#define __INITRODATA_OR_MODULE .section ".rodata","a",%progbits
+#else
+#define __init_or_module __init
+#define __initdata_or_module __initdata
+#define __initconst_or_module __initconst
+#define __INIT_OR_MODULE __INIT
+#define __INITDATA_OR_MODULE __INITDATA
+#define __INITRODATA_OR_MODULE __INITRODATA
+#endif /*CONFIG_MODULES*/
+
/* Archs provide a method of finding the correct exception table. */
struct exception_table_entry;
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h
index 7c9b484..1f6526c 100644
--- a/include/linux/usb/cdc_ncm.h
+++ b/include/linux/usb/cdc_ncm.h
@@ -80,6 +80,9 @@
#define CDC_NCM_TIMER_INTERVAL_MIN 5UL
#define CDC_NCM_TIMER_INTERVAL_MAX (U32_MAX / NSEC_PER_USEC)
+/* Driver flags */
+#define CDC_NCM_FLAG_NDP_TO_END 0x02 /* NDP is placed at end of frame */
+
#define cdc_ncm_comm_intf_is_mbim(x) ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \
(x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE)
#define cdc_ncm_data_intf_is_mbim(x) ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB)
@@ -103,9 +106,11 @@
spinlock_t mtx;
atomic_t stop;
+ int drvflags;
u32 timer_interval;
u32 max_ndp_size;
+ struct usb_cdc_ncm_ndp16 *delayed_ndp16;
u32 tx_timer_pending;
u32 tx_curr_frame_num;
@@ -133,7 +138,7 @@
};
u8 cdc_ncm_select_altsetting(struct usb_interface *intf);
-int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
+int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags);
void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
struct sk_buff *cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign);
int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 986fddb..b0f898e 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1745,6 +1745,7 @@
char node_desc[64];
__be64 node_guid;
u32 local_dma_lkey;
+ u16 is_switch:1;
u8 node_type;
u8 phys_port_cnt;
@@ -1824,6 +1825,20 @@
u8 port_num);
/**
+ * rdma_cap_ib_switch - Check if the device is IB switch
+ * @device: Device to check
+ *
+ * Device driver is responsible for setting is_switch bit on
+ * in ib_device structure at init time.
+ *
+ * Return: true if the device is IB switch.
+ */
+static inline bool rdma_cap_ib_switch(const struct ib_device *device)
+{
+ return device->is_switch;
+}
+
+/**
* rdma_start_port - Return the first valid port number for the device
* specified
*
@@ -1833,7 +1848,7 @@
*/
static inline u8 rdma_start_port(const struct ib_device *device)
{
- return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1;
+ return rdma_cap_ib_switch(device) ? 0 : 1;
}
/**
@@ -1846,8 +1861,7 @@
*/
static inline u8 rdma_end_port(const struct ib_device *device)
{
- return (device->node_type == RDMA_NODE_IB_SWITCH) ?
- 0 : device->phys_port_cnt;
+ return rdma_cap_ib_switch(device) ? 0 : device->phys_port_cnt;
}
static inline bool rdma_protocol_ib(const struct ib_device *device, u8 port_num)
diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h
index cdb05dd1..d40d3ef 100644
--- a/include/scsi/scsi_transport_srp.h
+++ b/include/scsi/scsi_transport_srp.h
@@ -119,6 +119,7 @@
extern void srp_rport_del(struct srp_rport *);
extern int srp_tmo_valid(int reconnect_delay, int fast_io_fail_tmo,
int dev_loss_tmo);
+int srp_parse_tmo(int *tmo, const char *buf);
extern int srp_reconnect_rport(struct srp_rport *rport);
extern void srp_start_tl_fail_timers(struct srp_rport *rport);
extern void srp_remove_host(struct Scsi_Host *);
diff --git a/include/uapi/linux/netconf.h b/include/uapi/linux/netconf.h
index 669a1f0..23cbd34 100644
--- a/include/uapi/linux/netconf.h
+++ b/include/uapi/linux/netconf.h
@@ -15,6 +15,7 @@
NETCONFA_RP_FILTER,
NETCONFA_MC_FORWARDING,
NETCONFA_PROXY_NEIGH,
+ NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
__NETCONFA_MAX
};
#define NETCONFA_MAX (__NETCONFA_MAX - 1)
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index f060716..74bde81 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -444,6 +444,7 @@
TRACE_CONTROL_BIT,
+ TRACE_BRANCH_BIT,
/*
* Abuse of the trace_recursion.
* As we need a way to maintain state if we are tracing the function
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c
index a87b43f..e2e12ad 100644
--- a/kernel/trace/trace_branch.c
+++ b/kernel/trace/trace_branch.c
@@ -36,9 +36,12 @@
struct trace_branch *entry;
struct ring_buffer *buffer;
unsigned long flags;
- int cpu, pc;
+ int pc;
const char *p;
+ if (current->trace_recursion & TRACE_BRANCH_BIT)
+ return;
+
/*
* I would love to save just the ftrace_likely_data pointer, but
* this code can also be used by modules. Ugly things can happen
@@ -49,10 +52,10 @@
if (unlikely(!tr))
return;
- local_irq_save(flags);
- cpu = raw_smp_processor_id();
- data = per_cpu_ptr(tr->trace_buffer.data, cpu);
- if (atomic_inc_return(&data->disabled) != 1)
+ raw_local_irq_save(flags);
+ current->trace_recursion |= TRACE_BRANCH_BIT;
+ data = this_cpu_ptr(tr->trace_buffer.data);
+ if (atomic_read(&data->disabled))
goto out;
pc = preempt_count();
@@ -81,8 +84,8 @@
__buffer_unlock_commit(buffer, event);
out:
- atomic_dec(&data->disabled);
- local_irq_restore(flags);
+ current->trace_recursion &= ~TRACE_BRANCH_BIT;
+ raw_local_irq_restore(flags);
}
static inline
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index a60a6d3..cc0c697 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -610,6 +610,8 @@
iter->skip = 0;
}
+ iter->p = NULL;
+
/* Ensure we see any new tables. */
smp_rmb();
@@ -620,8 +622,6 @@
return ERR_PTR(-EAGAIN);
}
- iter->p = NULL;
-
return NULL;
}
EXPORT_SYMBOL_GPL(rhashtable_walk_next);
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index e97572b..0ff6e1b 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -42,6 +42,7 @@
} else {
skb_push(skb, ETH_HLEN);
br_drop_fake_rtable(skb);
+ skb_sender_cpu_clear(skb);
dev_queue_xmit(skb);
}
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index e29ad70..c11cf26 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -323,6 +323,7 @@
struct net_bridge_port_group *p;
struct net_bridge_port_group __rcu **pp;
struct net_bridge_mdb_htable *mdb;
+ unsigned long now = jiffies;
int err;
mdb = mlock_dereference(br->mdb, br);
@@ -347,6 +348,8 @@
if (unlikely(!p))
return -ENOMEM;
rcu_assign_pointer(*pp, p);
+ if (state == MDB_TEMPORARY)
+ mod_timer(&p->timer, now + br->multicast_membership_interval);
br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
return 0;
@@ -371,6 +374,7 @@
if (!p || p->br != br || p->state == BR_STATE_DISABLED)
return -EINVAL;
+ memset(&ip, 0, sizeof(ip));
ip.proto = entry->addr.proto;
if (ip.proto == htons(ETH_P_IP))
ip.u.ip4 = entry->addr.u.ip4;
@@ -417,20 +421,14 @@
if (!netif_running(br->dev) || br->multicast_disabled)
return -EINVAL;
+ memset(&ip, 0, sizeof(ip));
ip.proto = entry->addr.proto;
- if (ip.proto == htons(ETH_P_IP)) {
- if (timer_pending(&br->ip4_other_query.timer))
- return -EBUSY;
-
+ if (ip.proto == htons(ETH_P_IP))
ip.u.ip4 = entry->addr.u.ip4;
#if IS_ENABLED(CONFIG_IPV6)
- } else {
- if (timer_pending(&br->ip6_other_query.timer))
- return -EBUSY;
-
+ else
ip.u.ip6 = entry->addr.u.ip6;
#endif
- }
spin_lock_bh(&br->multicast_lock);
mdb = mlock_dereference(br->mdb, br);
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index d89f4fa..c8b9bcf 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -111,7 +111,7 @@
/* largest possible L2 header, see br_nf_dev_queue_xmit() */
#define NF_BRIDGE_MAX_MAC_HEADER_LENGTH (PPPOE_SES_HLEN + ETH_HLEN)
-#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
+#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) || IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
struct brnf_frag_data {
char mac[NF_BRIDGE_MAX_MAC_HEADER_LENGTH];
u8 encap_size;
@@ -694,6 +694,7 @@
}
#endif
+#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
static int br_nf_ip_fragment(struct sock *sk, struct sk_buff *skb,
int (*output)(struct sock *, struct sk_buff *))
{
@@ -712,6 +713,7 @@
return ip_do_fragment(sk, skb, output);
}
+#endif
static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
{
@@ -742,7 +744,7 @@
struct brnf_frag_data *data;
if (br_validate_ipv4(skb))
- return NF_DROP;
+ goto drop;
IPCB(skb)->frag_max_size = nf_bridge->frag_max_size;
@@ -767,7 +769,7 @@
struct brnf_frag_data *data;
if (br_validate_ipv6(skb))
- return NF_DROP;
+ goto drop;
IP6CB(skb)->frag_max_size = nf_bridge->frag_max_size;
@@ -782,12 +784,16 @@
if (v6ops)
return v6ops->fragment(sk, skb, br_nf_push_frag_xmit);
- else
- return -EMSGSIZE;
+
+ kfree_skb(skb);
+ return -EMSGSIZE;
}
#endif
nf_bridge_info_free(skb);
return br_dev_queue_push_xmit(sk, skb);
+ drop:
+ kfree_skb(skb);
+ return 0;
}
/* PF_BRIDGE/POST_ROUTING ********************************************/
diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c
index 6d12d26..13b7d1e 100644
--- a/net/bridge/br_netfilter_ipv6.c
+++ b/net/bridge/br_netfilter_ipv6.c
@@ -104,7 +104,7 @@
{
const struct ipv6hdr *hdr;
struct net_device *dev = skb->dev;
- struct inet6_dev *idev = in6_dev_get(skb->dev);
+ struct inet6_dev *idev = __in6_dev_get(skb->dev);
u32 pkt_len;
u8 ip6h_len = sizeof(struct ipv6hdr);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 6b67ed3..364bdc9 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -457,6 +457,8 @@
if (nla_len(attr) != sizeof(struct bridge_vlan_info))
return -EINVAL;
vinfo = nla_data(attr);
+ if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
+ return -EINVAL;
if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
if (vinfo_start)
return -EINVAL;
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 7933e62..166d436 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -89,6 +89,8 @@
struct s_stats can_stats; /* packet statistics */
struct s_pstats can_pstats; /* receive list statistics */
+static atomic_t skbcounter = ATOMIC_INIT(0);
+
/*
* af_can socket functions
*/
@@ -310,12 +312,8 @@
return err;
}
- if (newskb) {
- if (!(newskb->tstamp.tv64))
- __net_timestamp(newskb);
-
+ if (newskb)
netif_rx_ni(newskb);
- }
/* update statistics */
can_stats.tx_frames++;
@@ -683,6 +681,10 @@
can_stats.rx_frames++;
can_stats.rx_frames_delta++;
+ /* create non-zero unique skb identifier together with *skb */
+ while (!(can_skb_prv(skb)->skbcnt))
+ can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter);
+
rcu_read_lock();
/* deliver the packet to sockets listening on all devices */
diff --git a/net/can/bcm.c b/net/can/bcm.c
index b523453..a1ba687 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -261,6 +261,7 @@
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
+ can_skb_prv(skb)->skbcnt = 0;
memcpy(skb_put(skb, CFSIZ), cf, CFSIZ);
@@ -1217,6 +1218,7 @@
}
can_skb_prv(skb)->ifindex = dev->ifindex;
+ can_skb_prv(skb)->skbcnt = 0;
skb->dev = dev;
can_skb_set_owner(skb, sk);
err = can_send(skb, 1); /* send with loopback */
diff --git a/net/can/raw.c b/net/can/raw.c
index 31b9748..2e67b14 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -75,7 +75,7 @@
*/
struct uniqframe {
- ktime_t tstamp;
+ int skbcnt;
const struct sk_buff *skb;
unsigned int join_rx_count;
};
@@ -133,7 +133,7 @@
/* eliminate multiple filter matches for the same skb */
if (this_cpu_ptr(ro->uniq)->skb == oskb &&
- ktime_equal(this_cpu_ptr(ro->uniq)->tstamp, oskb->tstamp)) {
+ this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
if (ro->join_filters) {
this_cpu_inc(ro->uniq->join_rx_count);
/* drop frame until all enabled filters matched */
@@ -144,7 +144,7 @@
}
} else {
this_cpu_ptr(ro->uniq)->skb = oskb;
- this_cpu_ptr(ro->uniq)->tstamp = oskb->tstamp;
+ this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
this_cpu_ptr(ro->uniq)->join_rx_count = 1;
/* drop first frame to check all enabled filters? */
if (ro->join_filters && ro->count > 1)
@@ -749,6 +749,7 @@
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
+ can_skb_prv(skb)->skbcnt = 0;
err = memcpy_from_msg(skb_put(skb, size), msg, size);
if (err < 0)
diff --git a/net/core/dev.c b/net/core/dev.c
index 6778a99..a8e4dd4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -677,10 +677,6 @@
if (dev->netdev_ops && dev->netdev_ops->ndo_get_iflink)
return dev->netdev_ops->ndo_get_iflink(dev);
- /* If dev->rtnl_link_ops is set, it's a virtual interface. */
- if (dev->rtnl_link_ops)
- return 0;
-
return dev->ifindex;
}
EXPORT_SYMBOL(dev_get_iflink);
@@ -3452,6 +3448,8 @@
local_irq_save(flags);
rps_lock(sd);
+ if (!netif_running(skb->dev))
+ goto drop;
qlen = skb_queue_len(&sd->input_pkt_queue);
if (qlen <= netdev_max_backlog && !skb_flow_limit(skb, qlen)) {
if (qlen) {
@@ -3473,6 +3471,7 @@
goto enqueue;
}
+drop:
sd->dropped++;
rps_unlock(sd);
@@ -3775,8 +3774,6 @@
pt_prev = NULL;
- rcu_read_lock();
-
another_round:
skb->skb_iif = skb->dev->ifindex;
@@ -3786,7 +3783,7 @@
skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
skb = skb_vlan_untag(skb);
if (unlikely(!skb))
- goto unlock;
+ goto out;
}
#ifdef CONFIG_NET_CLS_ACT
@@ -3816,10 +3813,10 @@
if (static_key_false(&ingress_needed)) {
skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
if (!skb)
- goto unlock;
+ goto out;
if (nf_ingress(skb, &pt_prev, &ret, orig_dev) < 0)
- goto unlock;
+ goto out;
}
#endif
#ifdef CONFIG_NET_CLS_ACT
@@ -3837,7 +3834,7 @@
if (vlan_do_receive(&skb))
goto another_round;
else if (unlikely(!skb))
- goto unlock;
+ goto out;
}
rx_handler = rcu_dereference(skb->dev->rx_handler);
@@ -3849,7 +3846,7 @@
switch (rx_handler(&skb)) {
case RX_HANDLER_CONSUMED:
ret = NET_RX_SUCCESS;
- goto unlock;
+ goto out;
case RX_HANDLER_ANOTHER:
goto another_round;
case RX_HANDLER_EXACT:
@@ -3903,8 +3900,7 @@
ret = NET_RX_DROP;
}
-unlock:
- rcu_read_unlock();
+out:
return ret;
}
@@ -3935,29 +3931,30 @@
static int netif_receive_skb_internal(struct sk_buff *skb)
{
+ int ret;
+
net_timestamp_check(netdev_tstamp_prequeue, skb);
if (skb_defer_rx_timestamp(skb))
return NET_RX_SUCCESS;
+ rcu_read_lock();
+
#ifdef CONFIG_RPS
if (static_key_false(&rps_needed)) {
struct rps_dev_flow voidflow, *rflow = &voidflow;
- int cpu, ret;
-
- rcu_read_lock();
-
- cpu = get_rps_cpu(skb->dev, skb, &rflow);
+ int cpu = get_rps_cpu(skb->dev, skb, &rflow);
if (cpu >= 0) {
ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
rcu_read_unlock();
return ret;
}
- rcu_read_unlock();
}
#endif
- return __netif_receive_skb(skb);
+ ret = __netif_receive_skb(skb);
+ rcu_read_unlock();
+ return ret;
}
/**
@@ -4502,8 +4499,10 @@
struct sk_buff *skb;
while ((skb = __skb_dequeue(&sd->process_queue))) {
+ rcu_read_lock();
local_irq_enable();
__netif_receive_skb(skb);
+ rcu_read_unlock();
local_irq_disable();
input_queue_head_incr(sd);
if (++work >= quota) {
@@ -6139,6 +6138,7 @@
unlist_netdevice(dev);
dev->reg_state = NETREG_UNREGISTERING;
+ on_each_cpu(flush_backlog, dev, 1);
}
synchronize_net();
@@ -6409,7 +6409,8 @@
struct netdev_queue *tx;
size_t sz = count * sizeof(*tx);
- BUG_ON(count < 1 || count > 0xffff);
+ if (count < 1 || count > 0xffff)
+ return -EINVAL;
tx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
if (!tx) {
@@ -6773,8 +6774,6 @@
dev->reg_state = NETREG_UNREGISTERED;
- on_each_cpu(flush_backlog, dev, 1);
-
netdev_wait_allrefs(dev);
/* paranoia */
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index 9dfb88a..92d886f 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -66,7 +66,7 @@
NOTES.
- * avbps is scaled by 2^5, avpps is scaled by 2^10.
+ * avbps and avpps are scaled by 2^5.
* both values are reported as 32 bit unsigned values. bps can
overflow for fast links : max speed being 34360Mbit/sec
* Minimal interval is HZ/4=250msec (it is the greatest common divisor
@@ -85,10 +85,10 @@
struct gnet_stats_rate_est64 *rate_est;
spinlock_t *stats_lock;
int ewma_log;
+ u32 last_packets;
+ unsigned long avpps;
u64 last_bytes;
u64 avbps;
- u32 last_packets;
- u32 avpps;
struct rcu_head e_rcu;
struct rb_node node;
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
@@ -118,8 +118,8 @@
rcu_read_lock();
list_for_each_entry_rcu(e, &elist[idx].list, list) {
struct gnet_stats_basic_packed b = {0};
+ unsigned long rate;
u64 brate;
- u32 rate;
spin_lock(e->stats_lock);
read_lock(&est_lock);
@@ -133,10 +133,11 @@
e->avbps += (brate >> e->ewma_log) - (e->avbps >> e->ewma_log);
e->rate_est->bps = (e->avbps+0xF)>>5;
- rate = (b.packets - e->last_packets)<<(12 - idx);
+ rate = b.packets - e->last_packets;
+ rate <<= (7 - idx);
e->last_packets = b.packets;
e->avpps += (rate >> e->ewma_log) - (e->avpps >> e->ewma_log);
- e->rate_est->pps = (e->avpps+0x1FF)>>10;
+ e->rate_est->pps = (e->avpps + 0xF) >> 5;
skip:
read_unlock(&est_lock);
spin_unlock(e->stats_lock);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 05badbb..1ebdf1c 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3571,13 +3571,6 @@
pr_debug("%s removing thread\n", t->tsk->comm);
pktgen_rem_thread(t);
- /* Wait for kthread_stop */
- while (!kthread_should_stop()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- }
- __set_current_state(TASK_RUNNING);
-
return 0;
}
@@ -3769,6 +3762,7 @@
}
t->net = pn;
+ get_task_struct(p);
wake_up_process(p);
wait_for_completion(&t->start_done);
@@ -3891,6 +3885,7 @@
t = list_entry(q, struct pktgen_thread, th_list);
list_del(&t->th_list);
kthread_stop(t->tsk);
+ put_task_struct(t->tsk);
kfree(t);
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 01ced4a..9e433d5 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1328,10 +1328,6 @@
[IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED },
};
-static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = {
- [IFLA_VF_INFO] = { .type = NLA_NESTED },
-};
-
static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
[IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) },
[IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) },
@@ -1488,96 +1484,98 @@
return 0;
}
-static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
+static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
{
- int rem, err = -EINVAL;
- struct nlattr *vf;
const struct net_device_ops *ops = dev->netdev_ops;
+ int err = -EINVAL;
- nla_for_each_nested(vf, attr, rem) {
- switch (nla_type(vf)) {
- case IFLA_VF_MAC: {
- struct ifla_vf_mac *ivm;
- ivm = nla_data(vf);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_mac)
- err = ops->ndo_set_vf_mac(dev, ivm->vf,
- ivm->mac);
- break;
- }
- case IFLA_VF_VLAN: {
- struct ifla_vf_vlan *ivv;
- ivv = nla_data(vf);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_vlan)
- err = ops->ndo_set_vf_vlan(dev, ivv->vf,
- ivv->vlan,
- ivv->qos);
- break;
- }
- case IFLA_VF_TX_RATE: {
- struct ifla_vf_tx_rate *ivt;
- struct ifla_vf_info ivf;
- ivt = nla_data(vf);
- err = -EOPNOTSUPP;
- if (ops->ndo_get_vf_config)
- err = ops->ndo_get_vf_config(dev, ivt->vf,
- &ivf);
- if (err)
- break;
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_rate)
- err = ops->ndo_set_vf_rate(dev, ivt->vf,
- ivf.min_tx_rate,
- ivt->rate);
- break;
- }
- case IFLA_VF_RATE: {
- struct ifla_vf_rate *ivt;
- ivt = nla_data(vf);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_rate)
- err = ops->ndo_set_vf_rate(dev, ivt->vf,
- ivt->min_tx_rate,
- ivt->max_tx_rate);
- break;
- }
- case IFLA_VF_SPOOFCHK: {
- struct ifla_vf_spoofchk *ivs;
- ivs = nla_data(vf);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_spoofchk)
- err = ops->ndo_set_vf_spoofchk(dev, ivs->vf,
- ivs->setting);
- break;
- }
- case IFLA_VF_LINK_STATE: {
- struct ifla_vf_link_state *ivl;
- ivl = nla_data(vf);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_link_state)
- err = ops->ndo_set_vf_link_state(dev, ivl->vf,
- ivl->link_state);
- break;
- }
- case IFLA_VF_RSS_QUERY_EN: {
- struct ifla_vf_rss_query_en *ivrssq_en;
+ if (tb[IFLA_VF_MAC]) {
+ struct ifla_vf_mac *ivm = nla_data(tb[IFLA_VF_MAC]);
- ivrssq_en = nla_data(vf);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_rss_query_en)
- err = ops->ndo_set_vf_rss_query_en(dev,
- ivrssq_en->vf,
- ivrssq_en->setting);
- break;
- }
- default:
- err = -EINVAL;
- break;
- }
- if (err)
- break;
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_mac)
+ err = ops->ndo_set_vf_mac(dev, ivm->vf,
+ ivm->mac);
+ if (err < 0)
+ return err;
}
+
+ if (tb[IFLA_VF_VLAN]) {
+ struct ifla_vf_vlan *ivv = nla_data(tb[IFLA_VF_VLAN]);
+
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_vlan)
+ err = ops->ndo_set_vf_vlan(dev, ivv->vf, ivv->vlan,
+ ivv->qos);
+ if (err < 0)
+ return err;
+ }
+
+ if (tb[IFLA_VF_TX_RATE]) {
+ struct ifla_vf_tx_rate *ivt = nla_data(tb[IFLA_VF_TX_RATE]);
+ struct ifla_vf_info ivf;
+
+ err = -EOPNOTSUPP;
+ if (ops->ndo_get_vf_config)
+ err = ops->ndo_get_vf_config(dev, ivt->vf, &ivf);
+ if (err < 0)
+ return err;
+
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_rate)
+ err = ops->ndo_set_vf_rate(dev, ivt->vf,
+ ivf.min_tx_rate,
+ ivt->rate);
+ if (err < 0)
+ return err;
+ }
+
+ if (tb[IFLA_VF_RATE]) {
+ struct ifla_vf_rate *ivt = nla_data(tb[IFLA_VF_RATE]);
+
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_rate)
+ err = ops->ndo_set_vf_rate(dev, ivt->vf,
+ ivt->min_tx_rate,
+ ivt->max_tx_rate);
+ if (err < 0)
+ return err;
+ }
+
+ if (tb[IFLA_VF_SPOOFCHK]) {
+ struct ifla_vf_spoofchk *ivs = nla_data(tb[IFLA_VF_SPOOFCHK]);
+
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_spoofchk)
+ err = ops->ndo_set_vf_spoofchk(dev, ivs->vf,
+ ivs->setting);
+ if (err < 0)
+ return err;
+ }
+
+ if (tb[IFLA_VF_LINK_STATE]) {
+ struct ifla_vf_link_state *ivl = nla_data(tb[IFLA_VF_LINK_STATE]);
+
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_link_state)
+ err = ops->ndo_set_vf_link_state(dev, ivl->vf,
+ ivl->link_state);
+ if (err < 0)
+ return err;
+ }
+
+ if (tb[IFLA_VF_RSS_QUERY_EN]) {
+ struct ifla_vf_rss_query_en *ivrssq_en;
+
+ err = -EOPNOTSUPP;
+ ivrssq_en = nla_data(tb[IFLA_VF_RSS_QUERY_EN]);
+ if (ops->ndo_set_vf_rss_query_en)
+ err = ops->ndo_set_vf_rss_query_en(dev, ivrssq_en->vf,
+ ivrssq_en->setting);
+ if (err < 0)
+ return err;
+ }
+
return err;
}
@@ -1773,14 +1771,21 @@
}
if (tb[IFLA_VFINFO_LIST]) {
+ struct nlattr *vfinfo[IFLA_VF_MAX + 1];
struct nlattr *attr;
int rem;
+
nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) {
- if (nla_type(attr) != IFLA_VF_INFO) {
+ if (nla_type(attr) != IFLA_VF_INFO ||
+ nla_len(attr) < NLA_HDRLEN) {
err = -EINVAL;
goto errout;
}
- err = do_setvfinfo(dev, attr);
+ err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr,
+ ifla_vf_policy);
+ if (err < 0)
+ goto errout;
+ err = do_setvfinfo(dev, vfinfo);
if (err < 0)
goto errout;
status |= DO_SETLINK_NOTIFY;
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 392e29a..b445d49 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -630,7 +630,7 @@
continue;
cd->sw_addr = be32_to_cpup(sw_addr);
- if (cd->sw_addr > PHY_MAX_ADDR)
+ if (cd->sw_addr >= PHY_MAX_ADDR)
continue;
if (!of_property_read_u32(child, "eeprom-length", &eeprom_len))
@@ -642,6 +642,8 @@
continue;
port_index = be32_to_cpup(port_reg);
+ if (port_index >= DSA_MAX_PORTS)
+ break;
port_name = of_get_property(port, "label", NULL);
if (!port_name)
@@ -666,8 +668,6 @@
goto out_free_chip;
}
- if (port_index == DSA_MAX_PORTS)
- break;
}
}
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7498716..e813196 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1740,6 +1740,8 @@
size += nla_total_size(4);
if (type == -1 || type == NETCONFA_PROXY_NEIGH)
size += nla_total_size(4);
+ if (type == -1 || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN)
+ size += nla_total_size(4);
return size;
}
@@ -1780,6 +1782,10 @@
nla_put_s32(skb, NETCONFA_PROXY_NEIGH,
IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0)
goto nla_put_failure;
+ if ((type == -1 || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) &&
+ nla_put_s32(skb, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
+ IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0)
+ goto nla_put_failure;
nlmsg_end(skb, nlh);
return 0;
@@ -1819,6 +1825,7 @@
[NETCONFA_FORWARDING] = { .len = sizeof(int) },
[NETCONFA_RP_FILTER] = { .len = sizeof(int) },
[NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) },
+ [NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN] = { .len = sizeof(int) },
};
static int inet_netconf_get_devconf(struct sk_buff *in_skb,
@@ -2048,6 +2055,12 @@
inet_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
ifindex, cnf);
}
+ if (i == IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1 &&
+ new_value != old_value) {
+ ifindex = devinet_conf_ifindex(net, cnf);
+ inet_netconf_notify_devconf(net, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
+ ifindex, cnf);
+ }
}
return ret;
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 9bc2667..c3b1f3a 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -152,8 +152,8 @@
inet6_sk(sk)->tclass) < 0)
goto errout;
- if (ipv6_only_sock(sk) &&
- nla_put_u8(skb, INET_DIAG_SKV6ONLY, 1))
+ if (((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
+ nla_put_u8(skb, INET_DIAG_SKV6ONLY, ipv6_only_sock(sk)))
goto errout;
}
#endif
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 4c2c3ba..626d9e5 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -586,7 +586,8 @@
EXPORT_SYMBOL(ip_tunnel_encap);
static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
- struct rtable *rt, __be16 df)
+ struct rtable *rt, __be16 df,
+ const struct iphdr *inner_iph)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
@@ -603,7 +604,8 @@
if (skb->protocol == htons(ETH_P_IP)) {
if (!skb_is_gso(skb) &&
- (df & htons(IP_DF)) && mtu < pkt_size) {
+ (inner_iph->frag_off & htons(IP_DF)) &&
+ mtu < pkt_size) {
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
return -E2BIG;
@@ -737,7 +739,7 @@
goto tx_error;
}
- if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) {
+ if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) {
ip_rt_put(rt);
goto tx_error;
}
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 95c9b6e..92305a1 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -254,9 +254,10 @@
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
unsigned int verdict = NF_DROP;
const struct arphdr *arp;
- struct arpt_entry *e, *back;
+ struct arpt_entry *e, **jumpstack;
const char *indev, *outdev;
const void *table_base;
+ unsigned int cpu, stackidx = 0;
const struct xt_table_info *private;
struct xt_action_param acpar;
unsigned int addend;
@@ -270,15 +271,16 @@
local_bh_disable();
addend = xt_write_recseq_begin();
private = table->private;
+ cpu = smp_processor_id();
/*
* Ensure we load private-> members after we've fetched the base
* pointer.
*/
smp_read_barrier_depends();
table_base = private->entries;
+ jumpstack = (struct arpt_entry **)private->jumpstack[cpu];
e = get_entry(table_base, private->hook_entry[hook]);
- back = get_entry(table_base, private->underflow[hook]);
acpar.in = state->in;
acpar.out = state->out;
@@ -312,18 +314,23 @@
verdict = (unsigned int)(-v) - 1;
break;
}
- e = back;
- back = get_entry(table_base, back->comefrom);
+ if (stackidx == 0) {
+ e = get_entry(table_base,
+ private->underflow[hook]);
+ } else {
+ e = jumpstack[--stackidx];
+ e = arpt_next_entry(e);
+ }
continue;
}
if (table_base + v
!= arpt_next_entry(e)) {
- /* Save old back ptr in next entry */
- struct arpt_entry *next = arpt_next_entry(e);
- next->comefrom = (void *)back - table_base;
- /* set back pointer to next entry */
- back = next;
+ if (stackidx >= private->stacksize) {
+ verdict = NF_DROP;
+ break;
+ }
+ jumpstack[stackidx++] = e;
}
e = get_entry(table_base, v);
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index f2e464e..57990c9 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -331,10 +331,10 @@
if (offset < 0)
goto out;
- if (!ipv6_is_mld(skb, nexthdr, offset))
- goto out;
+ if (ipv6_is_mld(skb, nexthdr, offset))
+ deliver = true;
- deliver = true;
+ goto out;
}
/* unknown RA - process it normally */
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1a1122a..6090969 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -369,10 +369,7 @@
struct inet6_dev *idev;
dst_destroy_metrics_generic(dst);
-
- if (rt->rt6i_pcpu)
- free_percpu(rt->rt6i_pcpu);
-
+ free_percpu(rt->rt6i_pcpu);
rt6_uncached_list_del(rt);
idev = rt->rt6i_idev;
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index cd60d39..8a8b2ab 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -213,7 +213,7 @@
if (verdict == NF_ACCEPT) {
next_hook:
- verdict = nf_iterate(&nf_hooks[entry->state.pf][entry->state.hook],
+ verdict = nf_iterate(entry->state.hook_list,
skb, &entry->state, &elem);
}
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 8b117c9..0c0e8ec 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -269,6 +269,12 @@
}
}
+enum {
+ NFNL_BATCH_FAILURE = (1 << 0),
+ NFNL_BATCH_DONE = (1 << 1),
+ NFNL_BATCH_REPLAY = (1 << 2),
+};
+
static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
u_int16_t subsys_id)
{
@@ -276,13 +282,15 @@
struct net *net = sock_net(skb->sk);
const struct nfnetlink_subsystem *ss;
const struct nfnl_callback *nc;
- bool success = true, done = false;
static LIST_HEAD(err_list);
+ u32 status;
int err;
if (subsys_id >= NFNL_SUBSYS_COUNT)
return netlink_ack(skb, nlh, -EINVAL);
replay:
+ status = 0;
+
skb = netlink_skb_clone(oskb, GFP_KERNEL);
if (!skb)
return netlink_ack(oskb, nlh, -ENOMEM);
@@ -336,10 +344,10 @@
if (type == NFNL_MSG_BATCH_BEGIN) {
/* Malformed: Batch begin twice */
nfnl_err_reset(&err_list);
- success = false;
+ status |= NFNL_BATCH_FAILURE;
goto done;
} else if (type == NFNL_MSG_BATCH_END) {
- done = true;
+ status |= NFNL_BATCH_DONE;
goto done;
} else if (type < NLMSG_MIN_TYPE) {
err = -EINVAL;
@@ -382,11 +390,8 @@
* original skb.
*/
if (err == -EAGAIN) {
- nfnl_err_reset(&err_list);
- ss->abort(oskb);
- nfnl_unlock(subsys_id);
- kfree_skb(skb);
- goto replay;
+ status |= NFNL_BATCH_REPLAY;
+ goto next;
}
}
ack:
@@ -402,7 +407,7 @@
*/
nfnl_err_reset(&err_list);
netlink_ack(skb, nlmsg_hdr(oskb), -ENOMEM);
- success = false;
+ status |= NFNL_BATCH_FAILURE;
goto done;
}
/* We don't stop processing the batch on errors, thus,
@@ -410,19 +415,26 @@
* triggers.
*/
if (err)
- success = false;
+ status |= NFNL_BATCH_FAILURE;
}
-
+next:
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
if (msglen > skb->len)
msglen = skb->len;
skb_pull(skb, msglen);
}
done:
- if (success && done)
- ss->commit(oskb);
- else
+ if (status & NFNL_BATCH_REPLAY) {
ss->abort(oskb);
+ nfnl_err_reset(&err_list);
+ nfnl_unlock(subsys_id);
+ kfree_skb(skb);
+ goto replay;
+ } else if (status == NFNL_BATCH_DONE) {
+ ss->commit(oskb);
+ } else {
+ ss->abort(oskb);
+ }
nfnl_err_deliver(&err_list, oskb);
nfnl_unlock(subsys_id);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index dea9253..9a0ae71 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -158,7 +158,7 @@
out:
spin_unlock(&netlink_tap_lock);
- if (found && nt->module)
+ if (found)
module_put(nt->module);
return found ? 0 : -ENODEV;
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index 273b8bf..657ba9f 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -759,8 +759,10 @@
}
ibmr = rds_ib_alloc_fmr(rds_ibdev);
- if (IS_ERR(ibmr))
+ if (IS_ERR(ibmr)) {
+ rds_ib_dev_put(rds_ibdev);
return ibmr;
+ }
ret = rds_ib_map_fmr(rds_ibdev, ibmr, sg, nents);
if (ret == 0)
diff --git a/net/rds/transport.c b/net/rds/transport.c
index 8b4a6cd..83498e1 100644
--- a/net/rds/transport.c
+++ b/net/rds/transport.c
@@ -73,7 +73,7 @@
void rds_trans_put(struct rds_transport *trans)
{
- if (trans && trans->t_owner)
+ if (trans)
module_put(trans->t_owner);
}
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 84f77a0..9f2add3 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -171,8 +171,10 @@
* released.
*/
- attr->trans = SWITCHDEV_TRANS_ABORT;
- __switchdev_port_attr_set(dev, attr);
+ if (err != -EOPNOTSUPP) {
+ attr->trans = SWITCHDEV_TRANS_ABORT;
+ __switchdev_port_attr_set(dev, attr);
+ }
return err;
}
@@ -249,8 +251,10 @@
* released.
*/
- obj->trans = SWITCHDEV_TRANS_ABORT;
- __switchdev_port_obj_add(dev, obj);
+ if (err != -EOPNOTSUPP) {
+ obj->trans = SWITCHDEV_TRANS_ABORT;
+ __switchdev_port_obj_add(dev, obj);
+ }
return err;
}
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 46b6ed5..3a7567f 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2007,6 +2007,7 @@
res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
if (res)
goto exit;
+ security_sk_clone(sock->sk, new_sock->sk);
new_sk = new_sock->sk;
new_tsock = tipc_sk(new_sk);
diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
index 620e37f..1dd087d 100644
--- a/virt/kvm/vfio.c
+++ b/virt/kvm/vfio.c
@@ -155,6 +155,8 @@
list_add_tail(&kvg->node, &kv->group_list);
kvg->vfio_group = vfio_group;
+ kvm_arch_start_assignment(dev->kvm);
+
mutex_unlock(&kv->lock);
kvm_vfio_update_coherency(dev);
@@ -190,6 +192,8 @@
break;
}
+ kvm_arch_end_assignment(dev->kvm);
+
mutex_unlock(&kv->lock);
kvm_vfio_group_put_external_user(vfio_group);
@@ -239,6 +243,7 @@
kvm_vfio_group_put_external_user(kvg->vfio_group);
list_del(&kvg->node);
kfree(kvg);
+ kvm_arch_end_assignment(dev->kvm);
}
kvm_vfio_update_coherency(dev);