15045 lines
466 KiB
Diff
15045 lines
466 KiB
Diff
SPDX-FileCopyrightText: 1991-2024 kernel.org contributors
|
|
SPDX-FileCopyrightText: 2023-2024 Open Enterprise Linux Association <kernel-lts@openela.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
Patch kernel up to 4.14.341-openela
|
|
|
|
diff --git Documentation/ABI/testing/sysfs-class-net-queues Documentation/ABI/testing/sysfs-class-net-queues
|
|
index 0c0df91b1516..2734cd9ee43c 100644
|
|
--- Documentation/ABI/testing/sysfs-class-net-queues
|
|
+++ Documentation/ABI/testing/sysfs-class-net-queues
|
|
@@ -1,4 +1,4 @@
|
|
-What: /sys/class/<iface>/queues/rx-<queue>/rps_cpus
|
|
+What: /sys/class/net/<iface>/queues/rx-<queue>/rps_cpus
|
|
Date: March 2010
|
|
KernelVersion: 2.6.35
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -8,7 +8,7 @@ Description:
|
|
network device queue. Possible values depend on the number
|
|
of available CPU(s) in the system.
|
|
|
|
-What: /sys/class/<iface>/queues/rx-<queue>/rps_flow_cnt
|
|
+What: /sys/class/net/<iface>/queues/rx-<queue>/rps_flow_cnt
|
|
Date: April 2010
|
|
KernelVersion: 2.6.35
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -16,7 +16,7 @@ Description:
|
|
Number of Receive Packet Steering flows being currently
|
|
processed by this particular network device receive queue.
|
|
|
|
-What: /sys/class/<iface>/queues/tx-<queue>/tx_timeout
|
|
+What: /sys/class/net/<iface>/queues/tx-<queue>/tx_timeout
|
|
Date: November 2011
|
|
KernelVersion: 3.3
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -24,7 +24,7 @@ Description:
|
|
Indicates the number of transmit timeout events seen by this
|
|
network interface transmit queue.
|
|
|
|
-What: /sys/class/<iface>/queues/tx-<queue>/tx_maxrate
|
|
+What: /sys/class/net/<iface>/queues/tx-<queue>/tx_maxrate
|
|
Date: March 2015
|
|
KernelVersion: 4.1
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -32,7 +32,7 @@ Description:
|
|
A Mbps max-rate set for the queue, a value of zero means disabled,
|
|
default is disabled.
|
|
|
|
-What: /sys/class/<iface>/queues/tx-<queue>/xps_cpus
|
|
+What: /sys/class/net/<iface>/queues/tx-<queue>/xps_cpus
|
|
Date: November 2010
|
|
KernelVersion: 2.6.38
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -42,7 +42,7 @@ Description:
|
|
network device transmit queue. Possible vaules depend on the
|
|
number of available CPU(s) in the system.
|
|
|
|
-What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/hold_time
|
|
+What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/hold_time
|
|
Date: November 2011
|
|
KernelVersion: 3.3
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -51,7 +51,7 @@ Description:
|
|
of this particular network device transmit queue.
|
|
Default value is 1000.
|
|
|
|
-What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/inflight
|
|
+What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/inflight
|
|
Date: November 2011
|
|
KernelVersion: 3.3
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -59,7 +59,7 @@ Description:
|
|
Indicates the number of bytes (objects) in flight on this
|
|
network device transmit queue.
|
|
|
|
-What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit
|
|
+What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit
|
|
Date: November 2011
|
|
KernelVersion: 3.3
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -68,7 +68,7 @@ Description:
|
|
on this network device transmit queue. This value is clamped
|
|
to be within the bounds defined by limit_max and limit_min.
|
|
|
|
-What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit_max
|
|
+What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit_max
|
|
Date: November 2011
|
|
KernelVersion: 3.3
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -77,7 +77,7 @@ Description:
|
|
queued on this network device transmit queue. See
|
|
include/linux/dynamic_queue_limits.h for the default value.
|
|
|
|
-What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit_min
|
|
+What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit_min
|
|
Date: November 2011
|
|
KernelVersion: 3.3
|
|
Contact: netdev@vger.kernel.org
|
|
diff --git Documentation/ABI/testing/sysfs-class-net-statistics Documentation/ABI/testing/sysfs-class-net-statistics
|
|
index 397118de7b5e..53e508c6936a 100644
|
|
--- Documentation/ABI/testing/sysfs-class-net-statistics
|
|
+++ Documentation/ABI/testing/sysfs-class-net-statistics
|
|
@@ -1,4 +1,4 @@
|
|
-What: /sys/class/<iface>/statistics/collisions
|
|
+What: /sys/class/net/<iface>/statistics/collisions
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -6,7 +6,7 @@ Description:
|
|
Indicates the number of collisions seen by this network device.
|
|
This value might not be relevant with all MAC layers.
|
|
|
|
-What: /sys/class/<iface>/statistics/multicast
|
|
+What: /sys/class/net/<iface>/statistics/multicast
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -14,7 +14,7 @@ Description:
|
|
Indicates the number of multicast packets received by this
|
|
network device.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_bytes
|
|
+What: /sys/class/net/<iface>/statistics/rx_bytes
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -23,7 +23,7 @@ Description:
|
|
See the network driver for the exact meaning of when this
|
|
value is incremented.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_compressed
|
|
+What: /sys/class/net/<iface>/statistics/rx_compressed
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -32,7 +32,7 @@ Description:
|
|
network device. This value might only be relevant for interfaces
|
|
that support packet compression (e.g: PPP).
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_crc_errors
|
|
+What: /sys/class/net/<iface>/statistics/rx_crc_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -41,7 +41,7 @@ Description:
|
|
by this network device. Note that the specific meaning might
|
|
depend on the MAC layer used by the interface.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_dropped
|
|
+What: /sys/class/net/<iface>/statistics/rx_dropped
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -51,7 +51,15 @@ Description:
|
|
packet processing. See the network driver for the exact
|
|
meaning of this value.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_fifo_errors
|
|
+What: /sys/class/net/<iface>/statistics/rx_errors
|
|
+Date: April 2005
|
|
+KernelVersion: 2.6.12
|
|
+Contact: netdev@vger.kernel.org
|
|
+Description:
|
|
+ Indicates the number of receive errors on this network device.
|
|
+ See the network driver for the exact meaning of this value.
|
|
+
|
|
+What: /sys/class/net/<iface>/statistics/rx_fifo_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -60,7 +68,7 @@ Description:
|
|
network device. See the network driver for the exact
|
|
meaning of this value.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_frame_errors
|
|
+What: /sys/class/net/<iface>/statistics/rx_frame_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -70,7 +78,7 @@ Description:
|
|
on the MAC layer protocol used. See the network driver for
|
|
the exact meaning of this value.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_length_errors
|
|
+What: /sys/class/net/<iface>/statistics/rx_length_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -79,7 +87,7 @@ Description:
|
|
error, oversized or undersized. See the network driver for the
|
|
exact meaning of this value.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_missed_errors
|
|
+What: /sys/class/net/<iface>/statistics/rx_missed_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -88,7 +96,15 @@ Description:
|
|
due to lack of capacity in the receive side. See the network
|
|
driver for the exact meaning of this value.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_over_errors
|
|
+What: /sys/class/net/<iface>/statistics/rx_nohandler
|
|
+Date: February 2016
|
|
+KernelVersion: 4.6
|
|
+Contact: netdev@vger.kernel.org
|
|
+Description:
|
|
+ Indicates the number of received packets that were dropped on
|
|
+ an inactive device by the network core.
|
|
+
|
|
+What: /sys/class/net/<iface>/statistics/rx_over_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -98,7 +114,7 @@ Description:
|
|
(e.g: larger than MTU). See the network driver for the exact
|
|
meaning of this value.
|
|
|
|
-What: /sys/class/<iface>/statistics/rx_packets
|
|
+What: /sys/class/net/<iface>/statistics/rx_packets
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -106,7 +122,7 @@ Description:
|
|
Indicates the total number of good packets received by this
|
|
network device.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_aborted_errors
|
|
+What: /sys/class/net/<iface>/statistics/tx_aborted_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -116,7 +132,7 @@ Description:
|
|
a medium collision). See the network driver for the exact
|
|
meaning of this value.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_bytes
|
|
+What: /sys/class/net/<iface>/statistics/tx_bytes
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -127,7 +143,7 @@ Description:
|
|
transmitted packets or all packets that have been queued for
|
|
transmission.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_carrier_errors
|
|
+What: /sys/class/net/<iface>/statistics/tx_carrier_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -136,7 +152,7 @@ Description:
|
|
because of carrier errors (e.g: physical link down). See the
|
|
network driver for the exact meaning of this value.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_compressed
|
|
+What: /sys/class/net/<iface>/statistics/tx_compressed
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -145,7 +161,7 @@ Description:
|
|
this might only be relevant for devices that support
|
|
compression (e.g: PPP).
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_dropped
|
|
+What: /sys/class/net/<iface>/statistics/tx_dropped
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -154,7 +170,7 @@ Description:
|
|
See the driver for the exact reasons as to why the packets were
|
|
dropped.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_errors
|
|
+What: /sys/class/net/<iface>/statistics/tx_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -163,7 +179,7 @@ Description:
|
|
a network device. See the driver for the exact reasons as to
|
|
why the packets were dropped.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_fifo_errors
|
|
+What: /sys/class/net/<iface>/statistics/tx_fifo_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -172,7 +188,7 @@ Description:
|
|
FIFO error. See the driver for the exact reasons as to why the
|
|
packets were dropped.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_heartbeat_errors
|
|
+What: /sys/class/net/<iface>/statistics/tx_heartbeat_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -181,7 +197,7 @@ Description:
|
|
reported as heartbeat errors. See the driver for the exact
|
|
reasons as to why the packets were dropped.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_packets
|
|
+What: /sys/class/net/<iface>/statistics/tx_packets
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
@@ -190,7 +206,7 @@ Description:
|
|
device. See the driver for whether this reports the number of all
|
|
attempted or successful transmissions.
|
|
|
|
-What: /sys/class/<iface>/statistics/tx_window_errors
|
|
+What: /sys/class/net/<iface>/statistics/tx_window_errors
|
|
Date: April 2005
|
|
KernelVersion: 2.6.12
|
|
Contact: netdev@vger.kernel.org
|
|
diff --git Documentation/sound/soc/dapm.rst Documentation/sound/soc/dapm.rst
|
|
index 8e44107933ab..c3154ce6e1b2 100644
|
|
--- Documentation/sound/soc/dapm.rst
|
|
+++ Documentation/sound/soc/dapm.rst
|
|
@@ -234,7 +234,7 @@ corresponding soft power control. In this case it is necessary to create
|
|
a virtual widget - a widget with no control bits e.g.
|
|
::
|
|
|
|
- SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
|
|
+ SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
|
|
|
|
This can be used to merge to signal paths together in software.
|
|
|
|
diff --git Makefile Makefile
|
|
index 3e5a7d98a1e3..0a53d6d980f7 100644
|
|
--- Makefile
|
|
+++ Makefile
|
|
@@ -1,8 +1,8 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 4
|
|
PATCHLEVEL = 14
|
|
-SUBLEVEL = 336
|
|
-EXTRAVERSION =
|
|
+SUBLEVEL = 341
|
|
+EXTRAVERSION = -openela
|
|
NAME = Petit Gorille
|
|
|
|
# *DOCUMENTATION*
|
|
diff --git arch/arc/kernel/signal.c arch/arc/kernel/signal.c
|
|
index 68901f6f18ba..c36e642eb1a0 100644
|
|
--- arch/arc/kernel/signal.c
|
|
+++ arch/arc/kernel/signal.c
|
|
@@ -64,7 +64,7 @@ struct rt_sigframe {
|
|
unsigned int sigret_magic;
|
|
};
|
|
|
|
-static int save_arcv2_regs(struct sigcontext *mctx, struct pt_regs *regs)
|
|
+static int save_arcv2_regs(struct sigcontext __user *mctx, struct pt_regs *regs)
|
|
{
|
|
int err = 0;
|
|
#ifndef CONFIG_ISA_ARCOMPACT
|
|
@@ -77,12 +77,12 @@ static int save_arcv2_regs(struct sigcontext *mctx, struct pt_regs *regs)
|
|
#else
|
|
v2abi.r58 = v2abi.r59 = 0;
|
|
#endif
|
|
- err = __copy_to_user(&mctx->v2abi, &v2abi, sizeof(v2abi));
|
|
+ err = __copy_to_user(&mctx->v2abi, (void const *)&v2abi, sizeof(v2abi));
|
|
#endif
|
|
return err;
|
|
}
|
|
|
|
-static int restore_arcv2_regs(struct sigcontext *mctx, struct pt_regs *regs)
|
|
+static int restore_arcv2_regs(struct sigcontext __user *mctx, struct pt_regs *regs)
|
|
{
|
|
int err = 0;
|
|
#ifndef CONFIG_ISA_ARCOMPACT
|
|
diff --git arch/arm/boot/dts/imx1-ads.dts arch/arm/boot/dts/imx1-ads.dts
|
|
index 5ea28ee07cf4..c2ee0a6b74ac 100644
|
|
--- arch/arm/boot/dts/imx1-ads.dts
|
|
+++ arch/arm/boot/dts/imx1-ads.dts
|
|
@@ -81,7 +81,7 @@
|
|
pinctrl-0 = <&pinctrl_weim>;
|
|
status = "okay";
|
|
|
|
- nor: nor@0,0 {
|
|
+ nor: flash@0,0 {
|
|
compatible = "cfi-flash";
|
|
reg = <0 0x00000000 0x02000000>;
|
|
bank-width = <4>;
|
|
diff --git arch/arm/boot/dts/imx1-apf9328.dts arch/arm/boot/dts/imx1-apf9328.dts
|
|
index e8b4b52c2418..001984de53ff 100644
|
|
--- arch/arm/boot/dts/imx1-apf9328.dts
|
|
+++ arch/arm/boot/dts/imx1-apf9328.dts
|
|
@@ -50,7 +50,7 @@
|
|
pinctrl-0 = <&pinctrl_weim>;
|
|
status = "okay";
|
|
|
|
- nor: nor@0,0 {
|
|
+ nor: flash@0,0 {
|
|
compatible = "cfi-flash";
|
|
reg = <0 0x00000000 0x02000000>;
|
|
bank-width = <2>;
|
|
diff --git arch/arm/boot/dts/imx1.dtsi arch/arm/boot/dts/imx1.dtsi
|
|
index 38d712be5685..65e27c86468a 100644
|
|
--- arch/arm/boot/dts/imx1.dtsi
|
|
+++ arch/arm/boot/dts/imx1.dtsi
|
|
@@ -269,9 +269,12 @@
|
|
status = "disabled";
|
|
};
|
|
|
|
- esram: esram@00300000 {
|
|
+ esram: sram@300000 {
|
|
compatible = "mmio-sram";
|
|
reg = <0x00300000 0x20000>;
|
|
+ ranges = <0 0x00300000 0x20000>;
|
|
+ #address-cells = <1>;
|
|
+ #size-cells = <1>;
|
|
};
|
|
};
|
|
};
|
|
diff --git arch/arm/boot/dts/imx23-sansa.dts arch/arm/boot/dts/imx23-sansa.dts
|
|
index 221fd55e967e..3e532f4c86a4 100644
|
|
--- arch/arm/boot/dts/imx23-sansa.dts
|
|
+++ arch/arm/boot/dts/imx23-sansa.dts
|
|
@@ -174,10 +174,8 @@
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
compatible = "i2c-gpio";
|
|
- gpios = <
|
|
- &gpio1 24 0 /* SDA */
|
|
- &gpio1 22 0 /* SCL */
|
|
- >;
|
|
+ sda-gpios = <&gpio1 24 0>;
|
|
+ scl-gpios = <&gpio1 22 0>;
|
|
i2c-gpio,delay-us = <2>; /* ~100 kHz */
|
|
};
|
|
|
|
@@ -185,10 +183,8 @@
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
compatible = "i2c-gpio";
|
|
- gpios = <
|
|
- &gpio0 31 0 /* SDA */
|
|
- &gpio0 30 0 /* SCL */
|
|
- >;
|
|
+ sda-gpios = <&gpio0 31 0>;
|
|
+ scl-gpios = <&gpio0 30 0>;
|
|
i2c-gpio,delay-us = <2>; /* ~100 kHz */
|
|
|
|
touch: touch@20 {
|
|
diff --git arch/arm/boot/dts/imx23.dtsi arch/arm/boot/dts/imx23.dtsi
|
|
index 10d57f9cbb42..7a1613258e6c 100644
|
|
--- arch/arm/boot/dts/imx23.dtsi
|
|
+++ arch/arm/boot/dts/imx23.dtsi
|
|
@@ -413,7 +413,7 @@
|
|
status = "disabled";
|
|
};
|
|
|
|
- dma_apbx: dma-apbx@80024000 {
|
|
+ dma_apbx: dma-controller@80024000 {
|
|
compatible = "fsl,imx23-dma-apbx";
|
|
reg = <0x80024000 0x2000>;
|
|
interrupts = <7 5 9 26
|
|
diff --git arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
|
|
index d6f27641c0ef..8676a28f8b7a 100644
|
|
--- arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
|
|
+++ arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
|
|
@@ -34,7 +34,7 @@
|
|
pinctrl-0 = <&pinctrl_i2c1>;
|
|
status = "okay";
|
|
|
|
- pcf8563@51 {
|
|
+ rtc@51 {
|
|
compatible = "nxp,pcf8563";
|
|
reg = <0x51>;
|
|
};
|
|
diff --git arch/arm/boot/dts/imx27-apf27dev.dts arch/arm/boot/dts/imx27-apf27dev.dts
|
|
index 5f84b598e0d0..167f21434fbf 100644
|
|
--- arch/arm/boot/dts/imx27-apf27dev.dts
|
|
+++ arch/arm/boot/dts/imx27-apf27dev.dts
|
|
@@ -53,7 +53,7 @@
|
|
pinctrl-names = "default";
|
|
pinctrl-0 = <&pinctrl_gpio_leds>;
|
|
|
|
- user {
|
|
+ led-user {
|
|
label = "Heartbeat";
|
|
gpios = <&gpio6 14 GPIO_ACTIVE_HIGH>;
|
|
linux,default-trigger = "heartbeat";
|
|
diff --git arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi
|
|
index 2cf896c505f9..546b0544f8c9 100644
|
|
--- arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi
|
|
+++ arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi
|
|
@@ -45,7 +45,7 @@
|
|
pinctrl-0 = <&pinctrl_i2c1>;
|
|
status = "okay";
|
|
|
|
- pcf8563@51 {
|
|
+ rtc@51 {
|
|
compatible = "nxp,pcf8563";
|
|
reg = <0x51>;
|
|
};
|
|
@@ -102,7 +102,7 @@
|
|
&weim {
|
|
status = "okay";
|
|
|
|
- nor: nor@0,0 {
|
|
+ nor: flash@0,0 {
|
|
#address-cells = <1>;
|
|
#size-cells = <1>;
|
|
compatible = "cfi-flash";
|
|
diff --git arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
|
|
index c973c5d91875..1cd3251d21e1 100644
|
|
--- arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
|
|
+++ arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
|
|
@@ -326,7 +326,7 @@
|
|
&weim {
|
|
status = "okay";
|
|
|
|
- nor: nor@0,0 {
|
|
+ nor: flash@0,0 {
|
|
compatible = "cfi-flash";
|
|
reg = <0 0x00000000 0x02000000>;
|
|
bank-width = <2>;
|
|
diff --git arch/arm/boot/dts/imx27.dtsi arch/arm/boot/dts/imx27.dtsi
|
|
index 15d85f1f85fd..507159b5d1d4 100644
|
|
--- arch/arm/boot/dts/imx27.dtsi
|
|
+++ arch/arm/boot/dts/imx27.dtsi
|
|
@@ -600,6 +600,9 @@
|
|
iram: iram@ffff4c00 {
|
|
compatible = "mmio-sram";
|
|
reg = <0xffff4c00 0xb400>;
|
|
+ ranges = <0 0xffff4c00 0xb400>;
|
|
+ #address-cells = <1>;
|
|
+ #size-cells = <1>;
|
|
};
|
|
};
|
|
};
|
|
diff --git arch/arm/boot/dts/imx28.dtsi arch/arm/boot/dts/imx28.dtsi
|
|
index 2f4ebe0318d3..e489c480f4c0 100644
|
|
--- arch/arm/boot/dts/imx28.dtsi
|
|
+++ arch/arm/boot/dts/imx28.dtsi
|
|
@@ -985,7 +985,7 @@
|
|
status = "disabled";
|
|
};
|
|
|
|
- dma_apbx: dma-apbx@80024000 {
|
|
+ dma_apbx: dma-controller@80024000 {
|
|
compatible = "fsl,imx28-dma-apbx";
|
|
reg = <0x80024000 0x2000>;
|
|
interrupts = <78 79 66 0
|
|
diff --git arch/arm/boot/dts/imx7s.dtsi arch/arm/boot/dts/imx7s.dtsi
|
|
index 836550f2297a..1d158707b5de 100644
|
|
--- arch/arm/boot/dts/imx7s.dtsi
|
|
+++ arch/arm/boot/dts/imx7s.dtsi
|
|
@@ -674,7 +674,7 @@
|
|
};
|
|
|
|
lcdif: lcdif@30730000 {
|
|
- compatible = "fsl,imx7d-lcdif", "fsl,imx28-lcdif";
|
|
+ compatible = "fsl,imx7d-lcdif", "fsl,imx6sx-lcdif";
|
|
reg = <0x30730000 0x10000>;
|
|
interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
|
|
clocks = <&clks IMX7D_LCDIF_PIXEL_ROOT_CLK>,
|
|
@@ -1039,7 +1039,7 @@
|
|
gpmi: gpmi-nand@33002000{
|
|
compatible = "fsl,imx7d-gpmi-nand";
|
|
#address-cells = <1>;
|
|
- #size-cells = <1>;
|
|
+ #size-cells = <0>;
|
|
reg = <0x33002000 0x2000>, <0x33004000 0x4000>;
|
|
reg-names = "gpmi-nand", "bch";
|
|
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
|
diff --git arch/arm/boot/dts/rk3036.dtsi arch/arm/boot/dts/rk3036.dtsi
|
|
index 03cf0c84ac0a..b1ede7a1e8de 100644
|
|
--- arch/arm/boot/dts/rk3036.dtsi
|
|
+++ arch/arm/boot/dts/rk3036.dtsi
|
|
@@ -353,12 +353,20 @@
|
|
pinctrl-0 = <&hdmi_ctl>;
|
|
status = "disabled";
|
|
|
|
- hdmi_in: port {
|
|
+ ports {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
- hdmi_in_vop: endpoint@0 {
|
|
+
|
|
+ hdmi_in: port@0 {
|
|
reg = <0>;
|
|
- remote-endpoint = <&vop_out_hdmi>;
|
|
+
|
|
+ hdmi_in_vop: endpoint {
|
|
+ remote-endpoint = <&vop_out_hdmi>;
|
|
+ };
|
|
+ };
|
|
+
|
|
+ hdmi_out: port@1 {
|
|
+ reg = <1>;
|
|
};
|
|
};
|
|
};
|
|
diff --git arch/mips/alchemy/devboards/db1200.c arch/mips/alchemy/devboards/db1200.c
|
|
index ae81e05fcb2c..fe827f98ebf1 100644
|
|
--- arch/mips/alchemy/devboards/db1200.c
|
|
+++ arch/mips/alchemy/devboards/db1200.c
|
|
@@ -858,7 +858,7 @@ int __init db1200_dev_setup(void)
|
|
i2c_register_board_info(0, db1200_i2c_devs,
|
|
ARRAY_SIZE(db1200_i2c_devs));
|
|
spi_register_board_info(db1200_spi_devs,
|
|
- ARRAY_SIZE(db1200_i2c_devs));
|
|
+ ARRAY_SIZE(db1200_spi_devs));
|
|
|
|
/* SWITCHES: S6.8 I2C/SPI selector (OFF=I2C ON=SPI)
|
|
* S6.7 AC97/I2S selector (OFF=AC97 ON=I2S)
|
|
diff --git arch/mips/alchemy/devboards/db1550.c arch/mips/alchemy/devboards/db1550.c
|
|
index 7d3dfaa10231..aaee46fe582f 100644
|
|
--- arch/mips/alchemy/devboards/db1550.c
|
|
+++ arch/mips/alchemy/devboards/db1550.c
|
|
@@ -581,7 +581,7 @@ int __init db1550_dev_setup(void)
|
|
i2c_register_board_info(0, db1550_i2c_devs,
|
|
ARRAY_SIZE(db1550_i2c_devs));
|
|
spi_register_board_info(db1550_spi_devs,
|
|
- ARRAY_SIZE(db1550_i2c_devs));
|
|
+ ARRAY_SIZE(db1550_spi_devs));
|
|
|
|
c = clk_get(NULL, "psc0_intclk");
|
|
if (!IS_ERR(c)) {
|
|
diff --git arch/mips/include/asm/checksum.h arch/mips/include/asm/checksum.h
|
|
index 77cad232a1c6..d7f673a6ef6d 100644
|
|
--- arch/mips/include/asm/checksum.h
|
|
+++ arch/mips/include/asm/checksum.h
|
|
@@ -276,7 +276,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
|
|
" .set pop"
|
|
: "=&r" (sum), "=&r" (tmp)
|
|
: "r" (saddr), "r" (daddr),
|
|
- "0" (htonl(len)), "r" (htonl(proto)), "r" (sum));
|
|
+ "0" (htonl(len)), "r" (htonl(proto)), "r" (sum)
|
|
+ : "memory");
|
|
|
|
return csum_fold(sum);
|
|
}
|
|
diff --git arch/mips/kernel/elf.c arch/mips/kernel/elf.c
|
|
index 731325a61a78..d7d0a4872389 100644
|
|
--- arch/mips/kernel/elf.c
|
|
+++ arch/mips/kernel/elf.c
|
|
@@ -15,6 +15,7 @@
|
|
|
|
#include <asm/cpu-features.h>
|
|
#include <asm/cpu-info.h>
|
|
+#include <asm/fpu.h>
|
|
|
|
/* Whether to accept legacy-NaN and 2008-NaN user binaries. */
|
|
bool mips_use_nan_legacy;
|
|
@@ -311,6 +312,11 @@ void mips_set_personality_nan(struct arch_elf_state *state)
|
|
struct cpuinfo_mips *c = &boot_cpu_data;
|
|
struct task_struct *t = current;
|
|
|
|
+ /* Do this early so t->thread.fpu.fcr31 won't be clobbered in case
|
|
+ * we are preempted before the lose_fpu(0) in start_thread.
|
|
+ */
|
|
+ lose_fpu(0);
|
|
+
|
|
t->thread.fpu.fcr31 = c->fpu_csr31;
|
|
switch (state->nan_2008) {
|
|
case 0:
|
|
diff --git arch/parisc/kernel/firmware.c arch/parisc/kernel/firmware.c
|
|
index 906b7c882587..82f264621845 100644
|
|
--- arch/parisc/kernel/firmware.c
|
|
+++ arch/parisc/kernel/firmware.c
|
|
@@ -127,10 +127,10 @@ static unsigned long f_extend(unsigned long address)
|
|
#ifdef CONFIG_64BIT
|
|
if(unlikely(parisc_narrow_firmware)) {
|
|
if((address & 0xff000000) == 0xf0000000)
|
|
- return 0xf0f0f0f000000000UL | (u32)address;
|
|
+ return (0xfffffff0UL << 32) | (u32)address;
|
|
|
|
if((address & 0xf0000000) == 0xf0000000)
|
|
- return 0xffffffff00000000UL | (u32)address;
|
|
+ return (0xffffffffUL << 32) | (u32)address;
|
|
}
|
|
#endif
|
|
return address;
|
|
diff --git arch/powerpc/Kconfig arch/powerpc/Kconfig
|
|
index 3fcfa8534156..ff7a86090eac 100644
|
|
--- arch/powerpc/Kconfig
|
|
+++ arch/powerpc/Kconfig
|
|
@@ -281,12 +281,10 @@ config ARCH_MAY_HAVE_PC_FDC
|
|
|
|
config PPC_UDBG_16550
|
|
bool
|
|
- default n
|
|
|
|
config GENERIC_TBSYNC
|
|
bool
|
|
default y if PPC32 && SMP
|
|
- default n
|
|
|
|
config AUDIT_ARCH
|
|
bool
|
|
@@ -305,13 +303,11 @@ config EPAPR_BOOT
|
|
bool
|
|
help
|
|
Used to allow a board to specify it wants an ePAPR compliant wrapper.
|
|
- default n
|
|
|
|
config DEFAULT_UIMAGE
|
|
bool
|
|
help
|
|
Used to allow a board to specify it wants a uImage built by default
|
|
- default n
|
|
|
|
config ARCH_HIBERNATION_POSSIBLE
|
|
bool
|
|
@@ -325,11 +321,9 @@ config ARCH_SUSPEND_POSSIBLE
|
|
|
|
config PPC_DCR_NATIVE
|
|
bool
|
|
- default n
|
|
|
|
config PPC_DCR_MMIO
|
|
bool
|
|
- default n
|
|
|
|
config PPC_DCR
|
|
bool
|
|
@@ -340,7 +334,6 @@ config PPC_OF_PLATFORM_PCI
|
|
bool
|
|
depends on PCI
|
|
depends on PPC64 # not supported on 32 bits yet
|
|
- default n
|
|
|
|
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
|
|
depends on PPC32 || PPC_STD_MMU_64
|
|
@@ -449,14 +442,12 @@ config PPC_TRANSACTIONAL_MEM
|
|
depends on SMP
|
|
select ALTIVEC
|
|
select VSX
|
|
- default n
|
|
---help---
|
|
Support user-mode Transactional Memory on POWERPC.
|
|
|
|
config LD_HEAD_STUB_CATCH
|
|
bool "Reserve 256 bytes to cope with linker stubs in HEAD text" if EXPERT
|
|
depends on PPC64
|
|
- default n
|
|
help
|
|
Very large kernels can cause linker branch stubs to be generated by
|
|
code in head_64.S, which moves the head text sections out of their
|
|
@@ -583,7 +574,6 @@ config RELOCATABLE
|
|
config RELOCATABLE_TEST
|
|
bool "Test relocatable kernel"
|
|
depends on (PPC64 && RELOCATABLE)
|
|
- default n
|
|
help
|
|
This runs the relocatable kernel at the address it was initially
|
|
loaded at, which tends to be non-zero and therefore test the
|
|
@@ -797,7 +787,6 @@ config PPC_SUBPAGE_PROT
|
|
|
|
config PPC_COPRO_BASE
|
|
bool
|
|
- default n
|
|
|
|
config SCHED_SMT
|
|
bool "SMT (Hyperthreading) scheduler support"
|
|
@@ -911,7 +900,6 @@ config PPC_INDIRECT_PCI
|
|
bool
|
|
depends on PCI
|
|
default y if 40x || 44x
|
|
- default n
|
|
|
|
config EISA
|
|
bool
|
|
@@ -1008,7 +996,6 @@ source "drivers/pcmcia/Kconfig"
|
|
|
|
config HAS_RAPIDIO
|
|
bool
|
|
- default n
|
|
|
|
config RAPIDIO
|
|
tristate "RapidIO support"
|
|
@@ -1044,7 +1031,6 @@ endmenu
|
|
|
|
config NONSTATIC_KERNEL
|
|
bool
|
|
- default n
|
|
|
|
menu "Advanced setup"
|
|
depends on PPC32
|
|
diff --git arch/powerpc/Kconfig.debug arch/powerpc/Kconfig.debug
|
|
index 6c60cc03a53c..a185e7c3fc9c 100644
|
|
--- arch/powerpc/Kconfig.debug
|
|
+++ arch/powerpc/Kconfig.debug
|
|
@@ -5,7 +5,6 @@ source "lib/Kconfig.debug"
|
|
|
|
config PPC_DISABLE_WERROR
|
|
bool "Don't build arch/powerpc code with -Werror"
|
|
- default n
|
|
help
|
|
This option tells the compiler NOT to build the code under
|
|
arch/powerpc with the -Werror flag (which means warnings
|
|
@@ -59,7 +58,6 @@ config PPC_EMULATED_STATS
|
|
config CODE_PATCHING_SELFTEST
|
|
bool "Run self-tests of the code-patching code"
|
|
depends on DEBUG_KERNEL
|
|
- default n
|
|
|
|
config JUMP_LABEL_FEATURE_CHECKS
|
|
bool "Enable use of jump label for cpu/mmu_has_feature()"
|
|
@@ -73,7 +71,6 @@ config JUMP_LABEL_FEATURE_CHECKS
|
|
config JUMP_LABEL_FEATURE_CHECK_DEBUG
|
|
bool "Do extra check on feature fixup calls"
|
|
depends on DEBUG_KERNEL && JUMP_LABEL_FEATURE_CHECKS
|
|
- default n
|
|
help
|
|
This tries to catch incorrect usage of cpu_has_feature() and
|
|
mmu_has_feature() in the code.
|
|
@@ -83,12 +80,10 @@ config JUMP_LABEL_FEATURE_CHECK_DEBUG
|
|
config FTR_FIXUP_SELFTEST
|
|
bool "Run self-tests of the feature-fixup code"
|
|
depends on DEBUG_KERNEL
|
|
- default n
|
|
|
|
config MSI_BITMAP_SELFTEST
|
|
bool "Run self-tests of the MSI bitmap code"
|
|
depends on DEBUG_KERNEL
|
|
- default n
|
|
|
|
config XMON
|
|
bool "Include xmon kernel debugger"
|
|
diff --git arch/powerpc/include/asm/mmu.h arch/powerpc/include/asm/mmu.h
|
|
index 6364f5c2cc3e..2cc99f5dd703 100644
|
|
--- arch/powerpc/include/asm/mmu.h
|
|
+++ arch/powerpc/include/asm/mmu.h
|
|
@@ -332,5 +332,9 @@ static inline void mmu_early_init_devtree(void) { }
|
|
# include <asm/mmu-8xx.h>
|
|
#endif
|
|
|
|
+#if defined(CONFIG_FA_DUMP) || defined(CONFIG_PRESERVE_FA_DUMP)
|
|
+#define __HAVE_ARCH_RESERVED_KERNEL_PAGES
|
|
+#endif
|
|
+
|
|
#endif /* __KERNEL__ */
|
|
#endif /* _ASM_POWERPC_MMU_H_ */
|
|
diff --git arch/powerpc/include/asm/mmzone.h arch/powerpc/include/asm/mmzone.h
|
|
index 91c69ff53a8a..50c2198c2c76 100644
|
|
--- arch/powerpc/include/asm/mmzone.h
|
|
+++ arch/powerpc/include/asm/mmzone.h
|
|
@@ -42,9 +42,6 @@ u64 memory_hotplug_max(void);
|
|
#else
|
|
#define memory_hotplug_max() memblock_end_of_DRAM()
|
|
#endif /* CONFIG_NEED_MULTIPLE_NODES */
|
|
-#ifdef CONFIG_FA_DUMP
|
|
-#define __HAVE_ARCH_RESERVED_KERNEL_PAGES
|
|
-#endif
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif /* _ASM_MMZONE_H_ */
|
|
diff --git arch/powerpc/kernel/traps.c arch/powerpc/kernel/traps.c
|
|
index a507a6874d42..f70799febec4 100644
|
|
--- arch/powerpc/kernel/traps.c
|
|
+++ arch/powerpc/kernel/traps.c
|
|
@@ -1070,10 +1070,12 @@ static int emulate_instruction(struct pt_regs *regs)
|
|
return -EINVAL;
|
|
}
|
|
|
|
+#ifdef CONFIG_GENERIC_BUG
|
|
int is_valid_bugaddr(unsigned long addr)
|
|
{
|
|
return is_kernel_addr(addr);
|
|
}
|
|
+#endif
|
|
|
|
#ifdef CONFIG_MATH_EMULATION
|
|
static int emulate_math(struct pt_regs *regs)
|
|
diff --git arch/powerpc/lib/Makefile arch/powerpc/lib/Makefile
|
|
index 00c34be4c604..41491eb517cc 100644
|
|
--- arch/powerpc/lib/Makefile
|
|
+++ arch/powerpc/lib/Makefile
|
|
@@ -21,8 +21,8 @@ obj-$(CONFIG_PPC32) += div64.o copy_32.o crtsavres.o
|
|
# 64-bit linker creates .sfpr on demand for final link (vmlinux),
|
|
# so it is only needed for modules, and only for older linkers which
|
|
# do not support --save-restore-funcs
|
|
-ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
|
|
-extra-$(CONFIG_PPC64) += crtsavres.o
|
|
+ifeq ($(call ld-ifversion, -lt, 225000000, y)$(CONFIG_PPC64),yy)
|
|
+always += crtsavres.o
|
|
endif
|
|
|
|
obj64-y += copypage_64.o copyuser_64.o mem_64.o hweight_64.o \
|
|
diff --git arch/powerpc/lib/sstep.c arch/powerpc/lib/sstep.c
|
|
index e9bfd9751246..331f3d0cbeb2 100644
|
|
--- arch/powerpc/lib/sstep.c
|
|
+++ arch/powerpc/lib/sstep.c
|
|
@@ -471,6 +471,8 @@ static int do_fp_load(struct instruction_op *op, unsigned long ea,
|
|
} u;
|
|
|
|
nb = GETSIZE(op->type);
|
|
+ if (nb > sizeof(u))
|
|
+ return -EINVAL;
|
|
if (!address_ok(regs, ea, nb))
|
|
return -EFAULT;
|
|
rn = op->reg;
|
|
@@ -521,6 +523,8 @@ static int do_fp_store(struct instruction_op *op, unsigned long ea,
|
|
} u;
|
|
|
|
nb = GETSIZE(op->type);
|
|
+ if (nb > sizeof(u))
|
|
+ return -EINVAL;
|
|
if (!address_ok(regs, ea, nb))
|
|
return -EFAULT;
|
|
rn = op->reg;
|
|
@@ -565,6 +569,9 @@ static nokprobe_inline int do_vec_load(int rn, unsigned long ea,
|
|
u8 b[sizeof(__vector128)];
|
|
} u = {};
|
|
|
|
+ if (size > sizeof(u))
|
|
+ return -EINVAL;
|
|
+
|
|
if (!address_ok(regs, ea & ~0xfUL, 16))
|
|
return -EFAULT;
|
|
/* align to multiple of size */
|
|
@@ -592,6 +599,9 @@ static nokprobe_inline int do_vec_store(int rn, unsigned long ea,
|
|
u8 b[sizeof(__vector128)];
|
|
} u;
|
|
|
|
+ if (size > sizeof(u))
|
|
+ return -EINVAL;
|
|
+
|
|
if (!address_ok(regs, ea & ~0xfUL, 16))
|
|
return -EFAULT;
|
|
/* align to multiple of size */
|
|
diff --git arch/powerpc/mm/init-common.c arch/powerpc/mm/init-common.c
|
|
index eb8c6c8c4851..c8515de5292e 100644
|
|
--- arch/powerpc/mm/init-common.c
|
|
+++ arch/powerpc/mm/init-common.c
|
|
@@ -65,7 +65,7 @@ void pgtable_cache_add(unsigned shift, void (*ctor)(void *))
|
|
* as to leave enough 0 bits in the address to contain it. */
|
|
unsigned long minalign = max(MAX_PGTABLE_INDEX_SIZE + 1,
|
|
HUGEPD_SHIFT_MASK + 1);
|
|
- struct kmem_cache *new;
|
|
+ struct kmem_cache *new = NULL;
|
|
|
|
/* It would be nice if this was a BUILD_BUG_ON(), but at the
|
|
* moment, gcc doesn't seem to recognize is_power_of_2 as a
|
|
@@ -78,7 +78,8 @@ void pgtable_cache_add(unsigned shift, void (*ctor)(void *))
|
|
|
|
align = max_t(unsigned long, align, minalign);
|
|
name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
|
|
- new = kmem_cache_create(name, table_size, align, 0, ctor);
|
|
+ if (name)
|
|
+ new = kmem_cache_create(name, table_size, align, 0, ctor);
|
|
if (!new)
|
|
panic("Could not allocate pgtable cache for order %d", shift);
|
|
|
|
diff --git arch/powerpc/perf/imc-pmu.c arch/powerpc/perf/imc-pmu.c
|
|
index a0b4c22d963a..0b785c6bdbbf 100644
|
|
--- arch/powerpc/perf/imc-pmu.c
|
|
+++ arch/powerpc/perf/imc-pmu.c
|
|
@@ -246,6 +246,8 @@ static int update_events_in_group(struct device_node *node, struct imc_pmu *pmu)
|
|
attr_group->attrs = attrs;
|
|
do {
|
|
ev_val_str = kasprintf(GFP_KERNEL, "event=0x%x", pmu->events[i]->value);
|
|
+ if (!ev_val_str)
|
|
+ continue;
|
|
dev_str = device_str_attr_create(pmu->events[i]->name, ev_val_str);
|
|
if (!dev_str)
|
|
continue;
|
|
@@ -253,6 +255,8 @@ static int update_events_in_group(struct device_node *node, struct imc_pmu *pmu)
|
|
attrs[j++] = dev_str;
|
|
if (pmu->events[i]->scale) {
|
|
ev_scale_str = kasprintf(GFP_KERNEL, "%s.scale",pmu->events[i]->name);
|
|
+ if (!ev_scale_str)
|
|
+ continue;
|
|
dev_str = device_str_attr_create(ev_scale_str, pmu->events[i]->scale);
|
|
if (!dev_str)
|
|
continue;
|
|
@@ -262,6 +266,8 @@ static int update_events_in_group(struct device_node *node, struct imc_pmu *pmu)
|
|
|
|
if (pmu->events[i]->unit) {
|
|
ev_unit_str = kasprintf(GFP_KERNEL, "%s.unit",pmu->events[i]->name);
|
|
+ if (!ev_unit_str)
|
|
+ continue;
|
|
dev_str = device_str_attr_create(ev_unit_str, pmu->events[i]->unit);
|
|
if (!dev_str)
|
|
continue;
|
|
diff --git arch/powerpc/platforms/40x/Kconfig arch/powerpc/platforms/40x/Kconfig
|
|
index 60254a321a91..2a9d66254ffc 100644
|
|
--- arch/powerpc/platforms/40x/Kconfig
|
|
+++ arch/powerpc/platforms/40x/Kconfig
|
|
@@ -2,7 +2,6 @@
|
|
config ACADIA
|
|
bool "Acadia"
|
|
depends on 40x
|
|
- default n
|
|
select PPC40x_SIMPLE
|
|
select 405EZ
|
|
help
|
|
@@ -11,7 +10,6 @@ config ACADIA
|
|
config EP405
|
|
bool "EP405/EP405PC"
|
|
depends on 40x
|
|
- default n
|
|
select 405GP
|
|
select PCI
|
|
help
|
|
@@ -20,7 +18,6 @@ config EP405
|
|
config HOTFOOT
|
|
bool "Hotfoot"
|
|
depends on 40x
|
|
- default n
|
|
select PPC40x_SIMPLE
|
|
select PCI
|
|
help
|
|
@@ -29,7 +26,6 @@ config HOTFOOT
|
|
config KILAUEA
|
|
bool "Kilauea"
|
|
depends on 40x
|
|
- default n
|
|
select 405EX
|
|
select PPC40x_SIMPLE
|
|
select PPC4xx_PCI_EXPRESS
|
|
@@ -41,7 +37,6 @@ config KILAUEA
|
|
config MAKALU
|
|
bool "Makalu"
|
|
depends on 40x
|
|
- default n
|
|
select 405EX
|
|
select PCI
|
|
select PPC4xx_PCI_EXPRESS
|
|
@@ -62,7 +57,6 @@ config WALNUT
|
|
config XILINX_VIRTEX_GENERIC_BOARD
|
|
bool "Generic Xilinx Virtex board"
|
|
depends on 40x
|
|
- default n
|
|
select XILINX_VIRTEX_II_PRO
|
|
select XILINX_VIRTEX_4_FX
|
|
select XILINX_INTC
|
|
@@ -80,7 +74,6 @@ config XILINX_VIRTEX_GENERIC_BOARD
|
|
config OBS600
|
|
bool "OpenBlockS 600"
|
|
depends on 40x
|
|
- default n
|
|
select 405EX
|
|
select PPC40x_SIMPLE
|
|
help
|
|
@@ -90,7 +83,6 @@ config OBS600
|
|
config PPC40x_SIMPLE
|
|
bool "Simple PowerPC 40x board support"
|
|
depends on 40x
|
|
- default n
|
|
help
|
|
This option enables the simple PowerPC 40x platform support.
|
|
|
|
@@ -156,7 +148,6 @@ config IBM405_ERR51
|
|
config APM8018X
|
|
bool "APM8018X"
|
|
depends on 40x
|
|
- default n
|
|
select PPC40x_SIMPLE
|
|
help
|
|
This option enables support for the AppliedMicro APM8018X evaluation
|
|
diff --git arch/powerpc/platforms/44x/Kconfig arch/powerpc/platforms/44x/Kconfig
|
|
index a6011422b861..559577065af2 100644
|
|
--- arch/powerpc/platforms/44x/Kconfig
|
|
+++ arch/powerpc/platforms/44x/Kconfig
|
|
@@ -2,7 +2,6 @@
|
|
config PPC_47x
|
|
bool "Support for 47x variant"
|
|
depends on 44x
|
|
- default n
|
|
select MPIC
|
|
help
|
|
This option enables support for the 47x family of processors and is
|
|
@@ -11,7 +10,6 @@ config PPC_47x
|
|
config BAMBOO
|
|
bool "Bamboo"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 440EP
|
|
select PCI
|
|
@@ -21,7 +19,6 @@ config BAMBOO
|
|
config BLUESTONE
|
|
bool "Bluestone"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select APM821xx
|
|
select PCI_MSI
|
|
@@ -44,7 +41,6 @@ config EBONY
|
|
config SAM440EP
|
|
bool "Sam440ep"
|
|
depends on 44x
|
|
- default n
|
|
select 440EP
|
|
select PCI
|
|
help
|
|
@@ -53,7 +49,6 @@ config SAM440EP
|
|
config SEQUOIA
|
|
bool "Sequoia"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 440EPX
|
|
help
|
|
@@ -62,7 +57,6 @@ config SEQUOIA
|
|
config TAISHAN
|
|
bool "Taishan"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 440GX
|
|
select PCI
|
|
@@ -73,7 +67,6 @@ config TAISHAN
|
|
config KATMAI
|
|
bool "Katmai"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 440SPe
|
|
select PCI
|
|
@@ -86,7 +79,6 @@ config KATMAI
|
|
config RAINIER
|
|
bool "Rainier"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 440GRX
|
|
select PCI
|
|
@@ -96,7 +88,6 @@ config RAINIER
|
|
config WARP
|
|
bool "PIKA Warp"
|
|
depends on 44x
|
|
- default n
|
|
select 440EP
|
|
help
|
|
This option enables support for the PIKA Warp(tm) Appliance. The Warp
|
|
@@ -109,7 +100,6 @@ config WARP
|
|
config ARCHES
|
|
bool "Arches"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 460EX # Odd since it uses 460GT but the effects are the same
|
|
select PCI
|
|
@@ -120,7 +110,6 @@ config ARCHES
|
|
config CANYONLANDS
|
|
bool "Canyonlands"
|
|
depends on 44x
|
|
- default n
|
|
select 460EX
|
|
select PCI
|
|
select PPC4xx_PCI_EXPRESS
|
|
@@ -134,7 +123,6 @@ config CANYONLANDS
|
|
config GLACIER
|
|
bool "Glacier"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 460EX # Odd since it uses 460GT but the effects are the same
|
|
select PCI
|
|
@@ -147,7 +135,6 @@ config GLACIER
|
|
config REDWOOD
|
|
bool "Redwood"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 460SX
|
|
select PCI
|
|
@@ -160,7 +147,6 @@ config REDWOOD
|
|
config EIGER
|
|
bool "Eiger"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 460SX
|
|
select PCI
|
|
@@ -172,7 +158,6 @@ config EIGER
|
|
config YOSEMITE
|
|
bool "Yosemite"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 440EP
|
|
select PCI
|
|
@@ -182,7 +167,6 @@ config YOSEMITE
|
|
config ISS4xx
|
|
bool "ISS 4xx Simulator"
|
|
depends on (44x || 40x)
|
|
- default n
|
|
select 405GP if 40x
|
|
select 440GP if 44x && !PPC_47x
|
|
select PPC_FPU
|
|
@@ -193,7 +177,7 @@ config ISS4xx
|
|
config CURRITUCK
|
|
bool "IBM Currituck (476fpe) Support"
|
|
depends on PPC_47x
|
|
- default n
|
|
+ select I2C
|
|
select SWIOTLB
|
|
select 476FPE
|
|
select PPC4xx_PCI_EXPRESS
|
|
@@ -203,7 +187,6 @@ config CURRITUCK
|
|
config FSP2
|
|
bool "IBM FSP2 (476fpe) Support"
|
|
depends on PPC_47x
|
|
- default n
|
|
select 476FPE
|
|
select IBM_EMAC_EMAC4 if IBM_EMAC
|
|
select IBM_EMAC_RGMII if IBM_EMAC
|
|
@@ -215,7 +198,6 @@ config FSP2
|
|
config AKEBONO
|
|
bool "IBM Akebono (476gtr) Support"
|
|
depends on PPC_47x
|
|
- default n
|
|
select SWIOTLB
|
|
select 476FPE
|
|
select PPC4xx_PCI_EXPRESS
|
|
@@ -241,7 +223,6 @@ config AKEBONO
|
|
config ICON
|
|
bool "Icon"
|
|
depends on 44x
|
|
- default n
|
|
select PPC44x_SIMPLE
|
|
select 440SPe
|
|
select PCI
|
|
@@ -252,7 +233,6 @@ config ICON
|
|
config XILINX_VIRTEX440_GENERIC_BOARD
|
|
bool "Generic Xilinx Virtex 5 FXT board support"
|
|
depends on 44x
|
|
- default n
|
|
select XILINX_VIRTEX_5_FXT
|
|
select XILINX_INTC
|
|
help
|
|
@@ -280,7 +260,6 @@ config XILINX_ML510
|
|
config PPC44x_SIMPLE
|
|
bool "Simple PowerPC 44x board support"
|
|
depends on 44x
|
|
- default n
|
|
help
|
|
This option enables the simple PowerPC 44x platform support.
|
|
|
|
diff --git arch/powerpc/platforms/82xx/Kconfig arch/powerpc/platforms/82xx/Kconfig
|
|
index 6e04099361b9..1947a88bc69f 100644
|
|
--- arch/powerpc/platforms/82xx/Kconfig
|
|
+++ arch/powerpc/platforms/82xx/Kconfig
|
|
@@ -51,7 +51,6 @@ endif
|
|
|
|
config PQ2ADS
|
|
bool
|
|
- default n
|
|
|
|
config 8260
|
|
bool
|
|
diff --git arch/powerpc/platforms/Kconfig arch/powerpc/platforms/Kconfig
|
|
index e06ccba35133..7cf557c1e1b0 100644
|
|
--- arch/powerpc/platforms/Kconfig
|
|
+++ arch/powerpc/platforms/Kconfig
|
|
@@ -23,7 +23,6 @@ source "arch/powerpc/platforms/amigaone/Kconfig"
|
|
|
|
config KVM_GUEST
|
|
bool "KVM Guest support"
|
|
- default n
|
|
select EPAPR_PARAVIRT
|
|
---help---
|
|
This option enables various optimizations for running under the KVM
|
|
@@ -34,7 +33,6 @@ config KVM_GUEST
|
|
|
|
config EPAPR_PARAVIRT
|
|
bool "ePAPR para-virtualization support"
|
|
- default n
|
|
help
|
|
Enables ePAPR para-virtualization support for guests.
|
|
|
|
@@ -74,7 +72,6 @@ config PPC_DT_CPU_FTRS
|
|
config UDBG_RTAS_CONSOLE
|
|
bool "RTAS based debug console"
|
|
depends on PPC_RTAS
|
|
- default n
|
|
|
|
config PPC_SMP_MUXED_IPI
|
|
bool
|
|
@@ -86,16 +83,13 @@ config PPC_SMP_MUXED_IPI
|
|
|
|
config IPIC
|
|
bool
|
|
- default n
|
|
|
|
config MPIC
|
|
bool
|
|
- default n
|
|
|
|
config MPIC_TIMER
|
|
bool "MPIC Global Timer"
|
|
depends on MPIC && FSL_SOC
|
|
- default n
|
|
help
|
|
The MPIC global timer is a hardware timer inside the
|
|
Freescale PIC complying with OpenPIC standard. When the
|
|
@@ -107,7 +101,6 @@ config MPIC_TIMER
|
|
config FSL_MPIC_TIMER_WAKEUP
|
|
tristate "Freescale MPIC global timer wakeup driver"
|
|
depends on FSL_SOC && MPIC_TIMER && PM
|
|
- default n
|
|
help
|
|
The driver provides a way to wake up the system by MPIC
|
|
timer.
|
|
@@ -115,43 +108,35 @@ config FSL_MPIC_TIMER_WAKEUP
|
|
|
|
config PPC_EPAPR_HV_PIC
|
|
bool
|
|
- default n
|
|
select EPAPR_PARAVIRT
|
|
|
|
config MPIC_WEIRD
|
|
bool
|
|
- default n
|
|
|
|
config MPIC_MSGR
|
|
bool "MPIC message register support"
|
|
depends on MPIC
|
|
- default n
|
|
help
|
|
Enables support for the MPIC message registers. These
|
|
registers are used for inter-processor communication.
|
|
|
|
config PPC_I8259
|
|
bool
|
|
- default n
|
|
|
|
config U3_DART
|
|
bool
|
|
depends on PPC64
|
|
- default n
|
|
|
|
config PPC_RTAS
|
|
bool
|
|
- default n
|
|
|
|
config RTAS_ERROR_LOGGING
|
|
bool
|
|
depends on PPC_RTAS
|
|
- default n
|
|
|
|
config PPC_RTAS_DAEMON
|
|
bool
|
|
depends on PPC_RTAS
|
|
- default n
|
|
|
|
config RTAS_PROC
|
|
bool "Proc interface to RTAS"
|
|
@@ -164,11 +149,9 @@ config RTAS_FLASH
|
|
|
|
config MMIO_NVRAM
|
|
bool
|
|
- default n
|
|
|
|
config MPIC_U3_HT_IRQS
|
|
bool
|
|
- default n
|
|
|
|
config MPIC_BROKEN_REGREAD
|
|
bool
|
|
@@ -187,15 +170,12 @@ config EEH
|
|
|
|
config PPC_MPC106
|
|
bool
|
|
- default n
|
|
|
|
config PPC_970_NAP
|
|
bool
|
|
- default n
|
|
|
|
config PPC_P7_NAP
|
|
bool
|
|
- default n
|
|
|
|
config PPC_INDIRECT_PIO
|
|
bool
|
|
@@ -301,7 +281,6 @@ config AXON_RAM
|
|
|
|
config FSL_ULI1575
|
|
bool
|
|
- default n
|
|
select GENERIC_ISA_DMA
|
|
help
|
|
Supports for the ULI1575 PCIe south bridge that exists on some
|
|
diff --git arch/powerpc/platforms/Kconfig.cputype arch/powerpc/platforms/Kconfig.cputype
|
|
index 3ce376b42330..267cc8f41cf1 100644
|
|
--- arch/powerpc/platforms/Kconfig.cputype
|
|
+++ arch/powerpc/platforms/Kconfig.cputype
|
|
@@ -1,7 +1,6 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
config PPC64
|
|
bool "64-bit kernel"
|
|
- default n
|
|
select ZLIB_DEFLATE
|
|
help
|
|
This option selects whether a 32-bit or a 64-bit kernel
|
|
@@ -326,7 +325,6 @@ config PPC_MM_SLICES
|
|
bool
|
|
default y if PPC_STD_MMU_64
|
|
default y if PPC_8xx && HUGETLB_PAGE
|
|
- default n
|
|
|
|
config PPC_HAVE_PMU_SUPPORT
|
|
bool
|
|
@@ -340,7 +338,6 @@ config PPC_PERF_CTRS
|
|
config FORCE_SMP
|
|
# Allow platforms to force SMP=y by selecting this
|
|
bool
|
|
- default n
|
|
select SMP
|
|
|
|
config SMP
|
|
@@ -381,7 +378,6 @@ config CHECK_CACHE_COHERENCY
|
|
|
|
config PPC_DOORBELL
|
|
bool
|
|
- default n
|
|
|
|
endmenu
|
|
|
|
diff --git arch/powerpc/platforms/cell/Kconfig arch/powerpc/platforms/cell/Kconfig
|
|
index 741a8fa8a3e6..3ad42075f1f4 100644
|
|
--- arch/powerpc/platforms/cell/Kconfig
|
|
+++ arch/powerpc/platforms/cell/Kconfig
|
|
@@ -1,7 +1,6 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
config PPC_CELL
|
|
bool
|
|
- default n
|
|
|
|
config PPC_CELL_COMMON
|
|
bool
|
|
@@ -22,7 +21,6 @@ config PPC_CELL_NATIVE
|
|
select IBM_EMAC_RGMII if IBM_EMAC
|
|
select IBM_EMAC_ZMII if IBM_EMAC #test only
|
|
select IBM_EMAC_TAH if IBM_EMAC #test only
|
|
- default n
|
|
|
|
config PPC_IBM_CELL_BLADE
|
|
bool "IBM Cell Blade"
|
|
@@ -55,7 +53,6 @@ config SPU_FS
|
|
|
|
config SPU_BASE
|
|
bool
|
|
- default n
|
|
select PPC_COPRO_BASE
|
|
|
|
config CBE_RAS
|
|
diff --git arch/powerpc/platforms/maple/Kconfig arch/powerpc/platforms/maple/Kconfig
|
|
index 376d0be36b66..2601fac50354 100644
|
|
--- arch/powerpc/platforms/maple/Kconfig
|
|
+++ arch/powerpc/platforms/maple/Kconfig
|
|
@@ -13,7 +13,6 @@ config PPC_MAPLE
|
|
select PPC_RTAS
|
|
select MMIO_NVRAM
|
|
select ATA_NONSTANDARD if ATA
|
|
- default n
|
|
help
|
|
This option enables support for the Maple 970FX Evaluation Board.
|
|
For more information, refer to <http://www.970eval.com>
|
|
diff --git arch/powerpc/platforms/pasemi/Kconfig arch/powerpc/platforms/pasemi/Kconfig
|
|
index d458a791d35b..98e3bc22bebc 100644
|
|
--- arch/powerpc/platforms/pasemi/Kconfig
|
|
+++ arch/powerpc/platforms/pasemi/Kconfig
|
|
@@ -2,7 +2,6 @@
|
|
config PPC_PASEMI
|
|
depends on PPC64 && PPC_BOOK3S && CPU_BIG_ENDIAN
|
|
bool "PA Semi SoC-based platforms"
|
|
- default n
|
|
select MPIC
|
|
select PCI
|
|
select PPC_UDBG_16550
|
|
diff --git arch/powerpc/platforms/powernv/Kconfig arch/powerpc/platforms/powernv/Kconfig
|
|
index f8dc98d3dc01..05ee7b65d40f 100644
|
|
--- arch/powerpc/platforms/powernv/Kconfig
|
|
+++ arch/powerpc/platforms/powernv/Kconfig
|
|
@@ -35,7 +35,6 @@ config OPAL_PRD
|
|
config PPC_MEMTRACE
|
|
bool "Enable removal of RAM from kernel mappings for tracing"
|
|
depends on PPC_POWERNV && MEMORY_HOTREMOVE
|
|
- default n
|
|
help
|
|
Enabling this option allows for the removal of memory (RAM)
|
|
from the kernel mappings to be used for hardware tracing.
|
|
diff --git arch/powerpc/platforms/powernv/opal-irqchip.c arch/powerpc/platforms/powernv/opal-irqchip.c
|
|
index ecdcba9d1220..bd37ff2d7bd2 100644
|
|
--- arch/powerpc/platforms/powernv/opal-irqchip.c
|
|
+++ arch/powerpc/platforms/powernv/opal-irqchip.c
|
|
@@ -253,6 +253,8 @@ int __init opal_event_init(void)
|
|
else
|
|
name = kasprintf(GFP_KERNEL, "opal");
|
|
|
|
+ if (!name)
|
|
+ continue;
|
|
/* Install interrupt handler */
|
|
rc = request_irq(virq, opal_interrupt, IRQF_TRIGGER_LOW,
|
|
name, NULL);
|
|
diff --git arch/powerpc/platforms/ps3/Kconfig arch/powerpc/platforms/ps3/Kconfig
|
|
index 6f7525555b19..24864b8aaf5d 100644
|
|
--- arch/powerpc/platforms/ps3/Kconfig
|
|
+++ arch/powerpc/platforms/ps3/Kconfig
|
|
@@ -49,7 +49,6 @@ config PS3_HTAB_SIZE
|
|
config PS3_DYNAMIC_DMA
|
|
depends on PPC_PS3
|
|
bool "PS3 Platform dynamic DMA page table management"
|
|
- default n
|
|
help
|
|
This option will enable kernel support to take advantage of the
|
|
per device dynamic DMA page table management provided by the Cell
|
|
@@ -89,7 +88,6 @@ config PS3_SYS_MANAGER
|
|
config PS3_REPOSITORY_WRITE
|
|
bool "PS3 Repository write support" if PS3_ADVANCED
|
|
depends on PPC_PS3
|
|
- default n
|
|
help
|
|
Enables support for writing to the PS3 System Repository.
|
|
|
|
diff --git arch/powerpc/platforms/pseries/Kconfig arch/powerpc/platforms/pseries/Kconfig
|
|
index 0c698fd6d491..39032d9b316c 100644
|
|
--- arch/powerpc/platforms/pseries/Kconfig
|
|
+++ arch/powerpc/platforms/pseries/Kconfig
|
|
@@ -28,7 +28,6 @@ config PPC_PSERIES
|
|
config PPC_SPLPAR
|
|
depends on PPC_PSERIES
|
|
bool "Support for shared-processor logical partitions"
|
|
- default n
|
|
help
|
|
Enabling this option will make the kernel run more efficiently
|
|
on logically-partitioned pSeries systems which use shared
|
|
@@ -99,7 +98,6 @@ config PPC_SMLPAR
|
|
bool "Support for shared-memory logical partitions"
|
|
depends on PPC_PSERIES
|
|
select LPARCFG
|
|
- default n
|
|
help
|
|
Select this option to enable shared memory partition support.
|
|
With this option a system running in an LPAR can be given more
|
|
diff --git arch/powerpc/platforms/pseries/hotplug-memory.c arch/powerpc/platforms/pseries/hotplug-memory.c
|
|
index 1a3cffdaa1e8..318772785547 100644
|
|
--- arch/powerpc/platforms/pseries/hotplug-memory.c
|
|
+++ arch/powerpc/platforms/pseries/hotplug-memory.c
|
|
@@ -573,7 +573,7 @@ static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
|
|
int lmb_found;
|
|
int i, rc;
|
|
|
|
- pr_info("Attempting to hot-remove LMB, drc index %x\n", drc_index);
|
|
+ pr_debug("Attempting to hot-remove LMB, drc index %x\n", drc_index);
|
|
|
|
p = prop->value;
|
|
num_lmbs = *p++;
|
|
@@ -591,14 +591,15 @@ static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
|
|
}
|
|
}
|
|
|
|
- if (!lmb_found)
|
|
+ if (!lmb_found) {
|
|
+ pr_debug("Failed to look up LMB for drc index %x\n", drc_index);
|
|
rc = -EINVAL;
|
|
-
|
|
- if (rc)
|
|
- pr_info("Failed to hot-remove memory at %llx\n",
|
|
- lmbs[i].base_addr);
|
|
- else
|
|
- pr_info("Memory at %llx was hot-removed\n", lmbs[i].base_addr);
|
|
+ } else if (rc) {
|
|
+ pr_debug("Failed to hot-remove memory at %llx\n",
|
|
+ lmbs[i].base_addr);
|
|
+ } else {
|
|
+ pr_debug("Memory at %llx was hot-removed\n", lmbs[i].base_addr);
|
|
+ }
|
|
|
|
return rc;
|
|
}
|
|
@@ -875,8 +876,8 @@ static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
|
|
if (!lmbs[i].reserved)
|
|
continue;
|
|
|
|
- pr_info("Memory at %llx (drc index %x) was hot-added\n",
|
|
- lmbs[i].base_addr, lmbs[i].drc_index);
|
|
+ pr_debug("Memory at %llx (drc index %x) was hot-added\n",
|
|
+ lmbs[i].base_addr, lmbs[i].drc_index);
|
|
lmbs[i].reserved = 0;
|
|
}
|
|
rc = 0;
|
|
diff --git arch/powerpc/sysdev/Kconfig arch/powerpc/sysdev/Kconfig
|
|
index bcef2ac56479..e0dbec780fe9 100644
|
|
--- arch/powerpc/sysdev/Kconfig
|
|
+++ arch/powerpc/sysdev/Kconfig
|
|
@@ -6,19 +6,16 @@
|
|
config PPC4xx_PCI_EXPRESS
|
|
bool
|
|
depends on PCI && 4xx
|
|
- default n
|
|
|
|
config PPC4xx_HSTA_MSI
|
|
bool
|
|
depends on PCI_MSI
|
|
depends on PCI && 4xx
|
|
- default n
|
|
|
|
config PPC4xx_MSI
|
|
bool
|
|
depends on PCI_MSI
|
|
depends on PCI && 4xx
|
|
- default n
|
|
|
|
config PPC_MSI_BITMAP
|
|
bool
|
|
@@ -37,11 +34,9 @@ config PPC_SCOM
|
|
config SCOM_DEBUGFS
|
|
bool "Expose SCOM controllers via debugfs"
|
|
depends on PPC_SCOM && DEBUG_FS
|
|
- default n
|
|
|
|
config GE_FPGA
|
|
bool
|
|
- default n
|
|
|
|
config FSL_CORENET_RCPM
|
|
bool
|
|
diff --git arch/powerpc/sysdev/xive/Kconfig arch/powerpc/sysdev/xive/Kconfig
|
|
index 70ee976e1de0..785c292d104b 100644
|
|
--- arch/powerpc/sysdev/xive/Kconfig
|
|
+++ arch/powerpc/sysdev/xive/Kconfig
|
|
@@ -1,17 +1,14 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
config PPC_XIVE
|
|
bool
|
|
- default n
|
|
select PPC_SMP_MUXED_IPI
|
|
select HARDIRQS_SW_RESEND
|
|
|
|
config PPC_XIVE_NATIVE
|
|
bool
|
|
- default n
|
|
select PPC_XIVE
|
|
depends on PPC_POWERNV
|
|
|
|
config PPC_XIVE_SPAPR
|
|
bool
|
|
- default n
|
|
select PPC_XIVE
|
|
diff --git arch/s390/kernel/ptrace.c arch/s390/kernel/ptrace.c
|
|
index 7c635e4328b8..60050ba8fa1d 100644
|
|
--- arch/s390/kernel/ptrace.c
|
|
+++ arch/s390/kernel/ptrace.c
|
|
@@ -411,6 +411,7 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
|
|
/*
|
|
* floating point control reg. is in the thread structure
|
|
*/
|
|
+ save_fpu_regs();
|
|
if ((unsigned int) data != 0 ||
|
|
test_fp_ctl(data >> (BITS_PER_LONG - 32)))
|
|
return -EINVAL;
|
|
@@ -771,6 +772,7 @@ static int __poke_user_compat(struct task_struct *child,
|
|
/*
|
|
* floating point control reg. is in the thread structure
|
|
*/
|
|
+ save_fpu_regs();
|
|
if (test_fp_ctl(tmp))
|
|
return -EINVAL;
|
|
child->thread.fpu.fpc = data;
|
|
@@ -999,9 +1001,7 @@ static int s390_fpregs_set(struct task_struct *target,
|
|
int rc = 0;
|
|
freg_t fprs[__NUM_FPRS];
|
|
|
|
- if (target == current)
|
|
- save_fpu_regs();
|
|
-
|
|
+ save_fpu_regs();
|
|
if (MACHINE_HAS_VX)
|
|
convert_vx_to_fp(fprs, target->thread.fpu.vxrs);
|
|
else
|
|
diff --git arch/s390/kvm/kvm-s390.c arch/s390/kvm/kvm-s390.c
|
|
index 05bd51752845..ee822b451eb2 100644
|
|
--- arch/s390/kvm/kvm-s390.c
|
|
+++ arch/s390/kvm/kvm-s390.c
|
|
@@ -2788,8 +2788,6 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
|
|
|
|
int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
|
|
{
|
|
- if (test_fp_ctl(fpu->fpc))
|
|
- return -EINVAL;
|
|
vcpu->run->s.regs.fpc = fpu->fpc;
|
|
if (MACHINE_HAS_VX)
|
|
convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs,
|
|
diff --git arch/s390/pci/pci.c arch/s390/pci/pci.c
|
|
index 960c4a362d8c..cf6a0af76c8f 100644
|
|
--- arch/s390/pci/pci.c
|
|
+++ arch/s390/pci/pci.c
|
|
@@ -272,7 +272,7 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
|
/* combine single writes by using store-block insn */
|
|
void __iowrite64_copy(void __iomem *to, const void *from, size_t count)
|
|
{
|
|
- zpci_memcpy_toio(to, from, count);
|
|
+ zpci_memcpy_toio(to, from, count * 8);
|
|
}
|
|
|
|
/* Create a virtual mapping cookie for a PCI BAR */
|
|
diff --git arch/um/drivers/net_kern.c arch/um/drivers/net_kern.c
|
|
index 1669240c7a25..f107c9598127 100644
|
|
--- arch/um/drivers/net_kern.c
|
|
+++ arch/um/drivers/net_kern.c
|
|
@@ -207,7 +207,7 @@ static int uml_net_close(struct net_device *dev)
|
|
return 0;
|
|
}
|
|
|
|
-static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
+static netdev_tx_t uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
{
|
|
struct uml_net_private *lp = netdev_priv(dev);
|
|
unsigned long flags;
|
|
diff --git arch/um/include/shared/kern_util.h arch/um/include/shared/kern_util.h
|
|
index 35ab97e4bb9b..f2da8347d5f5 100644
|
|
--- arch/um/include/shared/kern_util.h
|
|
+++ arch/um/include/shared/kern_util.h
|
|
@@ -49,7 +49,7 @@ extern void do_uml_exitcalls(void);
|
|
* Are we disallowed to sleep? Used to choose between GFP_KERNEL and
|
|
* GFP_ATOMIC.
|
|
*/
|
|
-extern int __cant_sleep(void);
|
|
+extern int __uml_cant_sleep(void);
|
|
extern int get_current_pid(void);
|
|
extern int copy_from_user_proc(void *to, void *from, int size);
|
|
extern int cpu(void);
|
|
diff --git arch/um/kernel/process.c arch/um/kernel/process.c
|
|
index 691b83b10649..c9d09d04d19d 100644
|
|
--- arch/um/kernel/process.c
|
|
+++ arch/um/kernel/process.c
|
|
@@ -210,7 +210,7 @@ void arch_cpu_idle(void)
|
|
local_irq_enable();
|
|
}
|
|
|
|
-int __cant_sleep(void) {
|
|
+int __uml_cant_sleep(void) {
|
|
return in_atomic() || irqs_disabled() || in_interrupt();
|
|
/* Is in_interrupt() really needed? */
|
|
}
|
|
diff --git arch/um/os-Linux/helper.c arch/um/os-Linux/helper.c
|
|
index 3f02d4232812..53d450e4a53a 100644
|
|
--- arch/um/os-Linux/helper.c
|
|
+++ arch/um/os-Linux/helper.c
|
|
@@ -45,7 +45,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
|
|
unsigned long stack, sp;
|
|
int pid, fds[2], ret, n;
|
|
|
|
- stack = alloc_stack(0, __cant_sleep());
|
|
+ stack = alloc_stack(0, __uml_cant_sleep());
|
|
if (stack == 0)
|
|
return -ENOMEM;
|
|
|
|
@@ -69,7 +69,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
|
|
data.pre_data = pre_data;
|
|
data.argv = argv;
|
|
data.fd = fds[1];
|
|
- data.buf = __cant_sleep() ? uml_kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
|
|
+ data.buf = __uml_cant_sleep() ? uml_kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
|
|
uml_kmalloc(PATH_MAX, UM_GFP_KERNEL);
|
|
pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
|
|
if (pid < 0) {
|
|
@@ -116,7 +116,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
|
|
unsigned long stack, sp;
|
|
int pid, status, err;
|
|
|
|
- stack = alloc_stack(0, __cant_sleep());
|
|
+ stack = alloc_stack(0, __uml_cant_sleep());
|
|
if (stack == 0)
|
|
return -ENOMEM;
|
|
|
|
diff --git arch/um/os-Linux/util.c arch/um/os-Linux/util.c
|
|
index 8cc8b2617a67..0436cc9537e0 100644
|
|
--- arch/um/os-Linux/util.c
|
|
+++ arch/um/os-Linux/util.c
|
|
@@ -166,23 +166,38 @@ __uml_setup("quiet", quiet_cmd_param,
|
|
"quiet\n"
|
|
" Turns off information messages during boot.\n\n");
|
|
|
|
+/*
|
|
+ * The os_info/os_warn functions will be called by helper threads. These
|
|
+ * have a very limited stack size and using the libc formatting functions
|
|
+ * may overflow the stack.
|
|
+ * So pull in the kernel vscnprintf and use that instead with a fixed
|
|
+ * on-stack buffer.
|
|
+ */
|
|
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
|
|
+
|
|
void os_info(const char *fmt, ...)
|
|
{
|
|
+ char buf[256];
|
|
va_list list;
|
|
+ int len;
|
|
|
|
if (quiet_info)
|
|
return;
|
|
|
|
va_start(list, fmt);
|
|
- vfprintf(stderr, fmt, list);
|
|
+ len = vscnprintf(buf, sizeof(buf), fmt, list);
|
|
+ fwrite(buf, len, 1, stderr);
|
|
va_end(list);
|
|
}
|
|
|
|
void os_warn(const char *fmt, ...)
|
|
{
|
|
+ char buf[256];
|
|
va_list list;
|
|
+ int len;
|
|
|
|
va_start(list, fmt);
|
|
- vfprintf(stderr, fmt, list);
|
|
+ len = vscnprintf(buf, sizeof(buf), fmt, list);
|
|
+ fwrite(buf, len, 1, stderr);
|
|
va_end(list);
|
|
}
|
|
diff --git arch/x86/kernel/cpu/amd.c arch/x86/kernel/cpu/amd.c
|
|
index 96305270c435..9ffb0cc5aa01 100644
|
|
--- arch/x86/kernel/cpu/amd.c
|
|
+++ arch/x86/kernel/cpu/amd.c
|
|
@@ -198,15 +198,6 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
|
|
return;
|
|
}
|
|
#endif
|
|
- /*
|
|
- * Work around Erratum 1386. The XSAVES instruction malfunctions in
|
|
- * certain circumstances on Zen1/2 uarch, and not all parts have had
|
|
- * updated microcode at the time of writing (March 2023).
|
|
- *
|
|
- * Affected parts all have no supervisor XSAVE states, meaning that
|
|
- * the XSAVEC instruction (which works fine) is equivalent.
|
|
- */
|
|
- clear_cpu_cap(c, X86_FEATURE_XSAVES);
|
|
}
|
|
|
|
static void init_amd_k7(struct cpuinfo_x86 *c)
|
|
@@ -880,6 +871,17 @@ static void init_amd_zn(struct cpuinfo_x86 *c)
|
|
if (c->x86 == 0x19 && !cpu_has(c, X86_FEATURE_BTC_NO))
|
|
set_cpu_cap(c, X86_FEATURE_BTC_NO);
|
|
}
|
|
+
|
|
+ /*
|
|
+ * Work around Erratum 1386. The XSAVES instruction malfunctions in
|
|
+ * certain circumstances on Zen1/2 uarch, and not all parts have had
|
|
+ * updated microcode at the time of writing (March 2023).
|
|
+ *
|
|
+ * Affected parts all have no supervisor XSAVE states, meaning that
|
|
+ * the XSAVEC instruction (which works fine) is equivalent.
|
|
+ */
|
|
+ if (c->x86 == 0x17)
|
|
+ clear_cpu_cap(c, X86_FEATURE_XSAVES);
|
|
}
|
|
|
|
static void init_amd(struct cpuinfo_x86 *c)
|
|
diff --git arch/x86/lib/misc.c arch/x86/lib/misc.c
|
|
index a018ec4fba53..c97be9a1430a 100644
|
|
--- arch/x86/lib/misc.c
|
|
+++ arch/x86/lib/misc.c
|
|
@@ -6,7 +6,7 @@
|
|
*/
|
|
int num_digits(int val)
|
|
{
|
|
- int m = 10;
|
|
+ long long m = 10;
|
|
int d = 1;
|
|
|
|
if (val < 0) {
|
|
diff --git arch/x86/mm/ident_map.c arch/x86/mm/ident_map.c
|
|
index 407fa1df470e..50c537a4554b 100644
|
|
--- arch/x86/mm/ident_map.c
|
|
+++ arch/x86/mm/ident_map.c
|
|
@@ -26,18 +26,31 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
|
|
for (; addr < end; addr = next) {
|
|
pud_t *pud = pud_page + pud_index(addr);
|
|
pmd_t *pmd;
|
|
+ bool use_gbpage;
|
|
|
|
next = (addr & PUD_MASK) + PUD_SIZE;
|
|
if (next > end)
|
|
next = end;
|
|
|
|
- if (info->direct_gbpages) {
|
|
- pud_t pudval;
|
|
+ /* if this is already a gbpage, this portion is already mapped */
|
|
+ if (pud_large(*pud))
|
|
+ continue;
|
|
+
|
|
+ /* Is using a gbpage allowed? */
|
|
+ use_gbpage = info->direct_gbpages;
|
|
|
|
- if (pud_present(*pud))
|
|
- continue;
|
|
+ /* Don't use gbpage if it maps more than the requested region. */
|
|
+ /* at the begining: */
|
|
+ use_gbpage &= ((addr & ~PUD_MASK) == 0);
|
|
+ /* ... or at the end: */
|
|
+ use_gbpage &= ((next & ~PUD_MASK) == 0);
|
|
+
|
|
+ /* Never overwrite existing mappings */
|
|
+ use_gbpage &= !pud_present(*pud);
|
|
+
|
|
+ if (use_gbpage) {
|
|
+ pud_t pudval;
|
|
|
|
- addr &= PUD_MASK;
|
|
pudval = __pud((addr - info->offset) | info->page_flag);
|
|
set_pud(pud, pudval);
|
|
continue;
|
|
diff --git block/bio.c block/bio.c
|
|
index 1eaf31976702..28e288243266 100644
|
|
--- block/bio.c
|
|
+++ block/bio.c
|
|
@@ -1723,7 +1723,7 @@ void bio_set_pages_dirty(struct bio *bio)
|
|
bio_for_each_segment_all(bvec, bio, i) {
|
|
struct page *page = bvec->bv_page;
|
|
|
|
- if (page && !PageCompound(page))
|
|
+ if (page)
|
|
set_page_dirty_lock(page);
|
|
}
|
|
}
|
|
@@ -1790,7 +1790,7 @@ void bio_check_pages_dirty(struct bio *bio)
|
|
bio_for_each_segment_all(bvec, bio, i) {
|
|
struct page *page = bvec->bv_page;
|
|
|
|
- if (PageDirty(page) || PageCompound(page)) {
|
|
+ if (PageDirty(page)) {
|
|
put_page(page);
|
|
bvec->bv_page = NULL;
|
|
} else {
|
|
diff --git crypto/af_alg.c crypto/af_alg.c
|
|
index da000a256e91..24de37ac9d27 100644
|
|
--- crypto/af_alg.c
|
|
+++ crypto/af_alg.c
|
|
@@ -1060,9 +1060,13 @@ EXPORT_SYMBOL_GPL(af_alg_sendpage);
|
|
void af_alg_free_resources(struct af_alg_async_req *areq)
|
|
{
|
|
struct sock *sk = areq->sk;
|
|
+ struct af_alg_ctx *ctx;
|
|
|
|
af_alg_free_areq_sgls(areq);
|
|
sock_kfree_s(sk, areq, areq->areqlen);
|
|
+
|
|
+ ctx = alg_sk(sk)->private;
|
|
+ ctx->inflight = false;
|
|
}
|
|
EXPORT_SYMBOL_GPL(af_alg_free_resources);
|
|
|
|
@@ -1126,11 +1130,19 @@ EXPORT_SYMBOL_GPL(af_alg_poll);
|
|
struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk,
|
|
unsigned int areqlen)
|
|
{
|
|
- struct af_alg_async_req *areq = sock_kmalloc(sk, areqlen, GFP_KERNEL);
|
|
+ struct af_alg_ctx *ctx = alg_sk(sk)->private;
|
|
+ struct af_alg_async_req *areq;
|
|
+
|
|
+ /* Only one AIO request can be in flight. */
|
|
+ if (ctx->inflight)
|
|
+ return ERR_PTR(-EBUSY);
|
|
|
|
+ areq = sock_kmalloc(sk, areqlen, GFP_KERNEL);
|
|
if (unlikely(!areq))
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
+ ctx->inflight = true;
|
|
+
|
|
areq->areqlen = areqlen;
|
|
areq->sk = sk;
|
|
areq->last_rsgl = NULL;
|
|
diff --git crypto/algapi.c crypto/algapi.c
|
|
index 603d2d637209..8557aff7fb35 100644
|
|
--- crypto/algapi.c
|
|
+++ crypto/algapi.c
|
|
@@ -222,6 +222,7 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
|
|
}
|
|
|
|
if (!strcmp(q->cra_driver_name, alg->cra_name) ||
|
|
+ !strcmp(q->cra_driver_name, alg->cra_driver_name) ||
|
|
!strcmp(q->cra_name, alg->cra_driver_name))
|
|
goto err;
|
|
}
|
|
diff --git crypto/scompress.c crypto/scompress.c
|
|
index 2075e2c4e7df..9baaf49f16bb 100644
|
|
--- crypto/scompress.c
|
|
+++ crypto/scompress.c
|
|
@@ -29,9 +29,17 @@
|
|
#include <crypto/internal/scompress.h>
|
|
#include "internal.h"
|
|
|
|
+struct scomp_scratch {
|
|
+ spinlock_t lock;
|
|
+ void *src;
|
|
+ void *dst;
|
|
+};
|
|
+
|
|
+static DEFINE_PER_CPU(struct scomp_scratch, scomp_scratch) = {
|
|
+ .lock = __SPIN_LOCK_UNLOCKED(scomp_scratch.lock),
|
|
+};
|
|
+
|
|
static const struct crypto_type crypto_scomp_type;
|
|
-static void * __percpu *scomp_src_scratches;
|
|
-static void * __percpu *scomp_dst_scratches;
|
|
static int scomp_scratch_users;
|
|
static DEFINE_MUTEX(scomp_lock);
|
|
|
|
@@ -65,76 +73,53 @@ static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
|
|
seq_puts(m, "type : scomp\n");
|
|
}
|
|
|
|
-static void crypto_scomp_free_scratches(void * __percpu *scratches)
|
|
+static void crypto_scomp_free_scratches(void)
|
|
{
|
|
+ struct scomp_scratch *scratch;
|
|
int i;
|
|
|
|
- if (!scratches)
|
|
- return;
|
|
-
|
|
- for_each_possible_cpu(i)
|
|
- vfree(*per_cpu_ptr(scratches, i));
|
|
+ for_each_possible_cpu(i) {
|
|
+ scratch = per_cpu_ptr(&scomp_scratch, i);
|
|
|
|
- free_percpu(scratches);
|
|
+ vfree(scratch->src);
|
|
+ vfree(scratch->dst);
|
|
+ scratch->src = NULL;
|
|
+ scratch->dst = NULL;
|
|
+ }
|
|
}
|
|
|
|
-static void * __percpu *crypto_scomp_alloc_scratches(void)
|
|
+static int crypto_scomp_alloc_scratches(void)
|
|
{
|
|
- void * __percpu *scratches;
|
|
+ struct scomp_scratch *scratch;
|
|
int i;
|
|
|
|
- scratches = alloc_percpu(void *);
|
|
- if (!scratches)
|
|
- return NULL;
|
|
-
|
|
for_each_possible_cpu(i) {
|
|
- void *scratch;
|
|
-
|
|
- scratch = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
|
|
- if (!scratch)
|
|
- goto error;
|
|
- *per_cpu_ptr(scratches, i) = scratch;
|
|
- }
|
|
+ void *mem;
|
|
|
|
- return scratches;
|
|
+ scratch = per_cpu_ptr(&scomp_scratch, i);
|
|
|
|
-error:
|
|
- crypto_scomp_free_scratches(scratches);
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-static void crypto_scomp_free_all_scratches(void)
|
|
-{
|
|
- if (!--scomp_scratch_users) {
|
|
- crypto_scomp_free_scratches(scomp_src_scratches);
|
|
- crypto_scomp_free_scratches(scomp_dst_scratches);
|
|
- scomp_src_scratches = NULL;
|
|
- scomp_dst_scratches = NULL;
|
|
- }
|
|
-}
|
|
-
|
|
-static int crypto_scomp_alloc_all_scratches(void)
|
|
-{
|
|
- if (!scomp_scratch_users++) {
|
|
- scomp_src_scratches = crypto_scomp_alloc_scratches();
|
|
- if (!scomp_src_scratches)
|
|
- return -ENOMEM;
|
|
- scomp_dst_scratches = crypto_scomp_alloc_scratches();
|
|
- if (!scomp_dst_scratches) {
|
|
- crypto_scomp_free_scratches(scomp_src_scratches);
|
|
- scomp_src_scratches = NULL;
|
|
- return -ENOMEM;
|
|
- }
|
|
+ mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
|
|
+ if (!mem)
|
|
+ goto error;
|
|
+ scratch->src = mem;
|
|
+ mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
|
|
+ if (!mem)
|
|
+ goto error;
|
|
+ scratch->dst = mem;
|
|
}
|
|
return 0;
|
|
+error:
|
|
+ crypto_scomp_free_scratches();
|
|
+ return -ENOMEM;
|
|
}
|
|
|
|
static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
|
|
{
|
|
- int ret;
|
|
+ int ret = 0;
|
|
|
|
mutex_lock(&scomp_lock);
|
|
- ret = crypto_scomp_alloc_all_scratches();
|
|
+ if (!scomp_scratch_users++)
|
|
+ ret = crypto_scomp_alloc_scratches();
|
|
mutex_unlock(&scomp_lock);
|
|
|
|
return ret;
|
|
@@ -193,42 +178,47 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
|
|
void **tfm_ctx = acomp_tfm_ctx(tfm);
|
|
struct crypto_scomp *scomp = *tfm_ctx;
|
|
void **ctx = acomp_request_ctx(req);
|
|
- const int cpu = get_cpu();
|
|
- u8 *scratch_src = *per_cpu_ptr(scomp_src_scratches, cpu);
|
|
- u8 *scratch_dst = *per_cpu_ptr(scomp_dst_scratches, cpu);
|
|
+ struct scomp_scratch *scratch;
|
|
+ unsigned int dlen;
|
|
int ret;
|
|
|
|
- if (!req->src || !req->slen || req->slen > SCOMP_SCRATCH_SIZE) {
|
|
- ret = -EINVAL;
|
|
- goto out;
|
|
- }
|
|
+ if (!req->src || !req->slen || req->slen > SCOMP_SCRATCH_SIZE)
|
|
+ return -EINVAL;
|
|
|
|
- if (req->dst && !req->dlen) {
|
|
- ret = -EINVAL;
|
|
- goto out;
|
|
- }
|
|
+ if (req->dst && !req->dlen)
|
|
+ return -EINVAL;
|
|
|
|
if (!req->dlen || req->dlen > SCOMP_SCRATCH_SIZE)
|
|
req->dlen = SCOMP_SCRATCH_SIZE;
|
|
|
|
- scatterwalk_map_and_copy(scratch_src, req->src, 0, req->slen, 0);
|
|
+ dlen = req->dlen;
|
|
+
|
|
+ scratch = raw_cpu_ptr(&scomp_scratch);
|
|
+ spin_lock(&scratch->lock);
|
|
+
|
|
+ scatterwalk_map_and_copy(scratch->src, req->src, 0, req->slen, 0);
|
|
if (dir)
|
|
- ret = crypto_scomp_compress(scomp, scratch_src, req->slen,
|
|
- scratch_dst, &req->dlen, *ctx);
|
|
+ ret = crypto_scomp_compress(scomp, scratch->src, req->slen,
|
|
+ scratch->dst, &req->dlen, *ctx);
|
|
else
|
|
- ret = crypto_scomp_decompress(scomp, scratch_src, req->slen,
|
|
- scratch_dst, &req->dlen, *ctx);
|
|
+ ret = crypto_scomp_decompress(scomp, scratch->src, req->slen,
|
|
+ scratch->dst, &req->dlen, *ctx);
|
|
if (!ret) {
|
|
if (!req->dst) {
|
|
req->dst = crypto_scomp_sg_alloc(req->dlen, GFP_ATOMIC);
|
|
- if (!req->dst)
|
|
+ if (!req->dst) {
|
|
+ ret = -ENOMEM;
|
|
goto out;
|
|
+ }
|
|
+ } else if (req->dlen > dlen) {
|
|
+ ret = -ENOSPC;
|
|
+ goto out;
|
|
}
|
|
- scatterwalk_map_and_copy(scratch_dst, req->dst, 0, req->dlen,
|
|
+ scatterwalk_map_and_copy(scratch->dst, req->dst, 0, req->dlen,
|
|
1);
|
|
}
|
|
out:
|
|
- put_cpu();
|
|
+ spin_unlock(&scratch->lock);
|
|
return ret;
|
|
}
|
|
|
|
@@ -249,7 +239,8 @@ static void crypto_exit_scomp_ops_async(struct crypto_tfm *tfm)
|
|
crypto_free_scomp(*ctx);
|
|
|
|
mutex_lock(&scomp_lock);
|
|
- crypto_scomp_free_all_scratches();
|
|
+ if (!--scomp_scratch_users)
|
|
+ crypto_scomp_free_scratches();
|
|
mutex_unlock(&scomp_lock);
|
|
}
|
|
|
|
diff --git drivers/acpi/acpi_extlog.c drivers/acpi/acpi_extlog.c
|
|
index e05309bc41cc..e148b0a28ec9 100644
|
|
--- drivers/acpi/acpi_extlog.c
|
|
+++ drivers/acpi/acpi_extlog.c
|
|
@@ -317,9 +317,10 @@ static void __exit extlog_exit(void)
|
|
{
|
|
edac_set_report_status(old_edac_report_status);
|
|
mce_unregister_decode_chain(&extlog_mce_dec);
|
|
- ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN;
|
|
- if (extlog_l1_addr)
|
|
+ if (extlog_l1_addr) {
|
|
+ ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN;
|
|
acpi_os_unmap_iomem(extlog_l1_addr, l1_size);
|
|
+ }
|
|
if (elog_addr)
|
|
acpi_os_unmap_iomem(elog_addr, elog_size);
|
|
release_mem_region(elog_base, elog_size);
|
|
diff --git drivers/acpi/acpi_video.c drivers/acpi/acpi_video.c
|
|
index cc228e5ad2b3..d426ece23a70 100644
|
|
--- drivers/acpi/acpi_video.c
|
|
+++ drivers/acpi/acpi_video.c
|
|
@@ -581,6 +581,15 @@ static const struct dmi_system_id video_dmi_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3350"),
|
|
},
|
|
},
|
|
+ {
|
|
+ .callback = video_set_report_key_events,
|
|
+ .driver_data = (void *)((uintptr_t)REPORT_BRIGHTNESS_KEY_EVENTS),
|
|
+ .ident = "COLORFUL X15 AT 23",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "COLORFUL"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "X15 AT 23"),
|
|
+ },
|
|
+ },
|
|
/*
|
|
* Some machines change the brightness themselves when a brightness
|
|
* hotkey gets pressed, despite us telling them not to. In this case
|
|
@@ -1796,12 +1805,12 @@ static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
|
|
return;
|
|
count++;
|
|
|
|
- acpi_get_parent(device->dev->handle, &acpi_parent);
|
|
-
|
|
- pdev = acpi_get_pci_dev(acpi_parent);
|
|
- if (pdev) {
|
|
- parent = &pdev->dev;
|
|
- pci_dev_put(pdev);
|
|
+ if (ACPI_SUCCESS(acpi_get_parent(device->dev->handle, &acpi_parent))) {
|
|
+ pdev = acpi_get_pci_dev(acpi_parent);
|
|
+ if (pdev) {
|
|
+ parent = &pdev->dev;
|
|
+ pci_dev_put(pdev);
|
|
+ }
|
|
}
|
|
|
|
memset(&props, 0, sizeof(struct backlight_properties));
|
|
diff --git drivers/android/binder_alloc.c drivers/android/binder_alloc.c
|
|
index f7f0b71c9f68..08f31fa30648 100644
|
|
--- drivers/android/binder_alloc.c
|
|
+++ drivers/android/binder_alloc.c
|
|
@@ -284,7 +284,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
|
|
}
|
|
if (mm) {
|
|
up_write(&mm->mmap_sem);
|
|
- mmput(mm);
|
|
+ mmput_async(mm);
|
|
}
|
|
return 0;
|
|
|
|
@@ -319,7 +319,7 @@ err_page_ptr_cleared:
|
|
err_no_vma:
|
|
if (mm) {
|
|
up_write(&mm->mmap_sem);
|
|
- mmput(mm);
|
|
+ mmput_async(mm);
|
|
}
|
|
return vma ? -ENOMEM : -ESRCH;
|
|
}
|
|
@@ -389,17 +389,17 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc,
|
|
alloc->pid, extra_buffers_size);
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
- if (is_async &&
|
|
- alloc->free_async_space < size + sizeof(struct binder_buffer)) {
|
|
+
|
|
+ /* Pad 0-size buffers so they get assigned unique addresses */
|
|
+ size = max(size, sizeof(void *));
|
|
+
|
|
+ if (is_async && alloc->free_async_space < size) {
|
|
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
|
|
"%d: binder_alloc_buf size %zd failed, no async space left\n",
|
|
alloc->pid, size);
|
|
return ERR_PTR(-ENOSPC);
|
|
}
|
|
|
|
- /* Pad 0-size buffers so they get assigned unique addresses */
|
|
- size = max(size, sizeof(void *));
|
|
-
|
|
while (n) {
|
|
buffer = rb_entry(n, struct binder_buffer, rb_node);
|
|
BUG_ON(!buffer->free);
|
|
@@ -496,7 +496,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc,
|
|
buffer->async_transaction = is_async;
|
|
buffer->extra_buffers_size = extra_buffers_size;
|
|
if (is_async) {
|
|
- alloc->free_async_space -= size + sizeof(struct binder_buffer);
|
|
+ alloc->free_async_space -= size;
|
|
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
|
|
"%d: binder_alloc_buf size %zd async free %zd\n",
|
|
alloc->pid, size, alloc->free_async_space);
|
|
@@ -523,7 +523,7 @@ err_alloc_buf_struct_failed:
|
|
* is the sum of the three given sizes (each rounded up to
|
|
* pointer-sized boundary)
|
|
*
|
|
- * Return: The allocated buffer or %NULL if error
|
|
+ * Return: The allocated buffer or %ERR_PTR(-errno) if error
|
|
*/
|
|
struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
|
|
size_t data_size,
|
|
@@ -619,8 +619,7 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,
|
|
BUG_ON(buffer->data > alloc->buffer + alloc->buffer_size);
|
|
|
|
if (buffer->async_transaction) {
|
|
- alloc->free_async_space += buffer_size + sizeof(struct binder_buffer);
|
|
-
|
|
+ alloc->free_async_space += buffer_size;
|
|
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
|
|
"%d: binder_free_buf size %zd async free %zd\n",
|
|
alloc->pid, size, alloc->free_async_space);
|
|
diff --git drivers/ata/ahci.c drivers/ata/ahci.c
|
|
index 5b810a290b93..c2e5ef709acb 100644
|
|
--- drivers/ata/ahci.c
|
|
+++ drivers/ata/ahci.c
|
|
@@ -605,6 +605,11 @@ MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
|
|
static void ahci_pci_save_initial_config(struct pci_dev *pdev,
|
|
struct ahci_host_priv *hpriv)
|
|
{
|
|
+ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1166) {
|
|
+ dev_info(&pdev->dev, "ASM1166 has only six ports\n");
|
|
+ hpriv->saved_port_map = 0x3f;
|
|
+ }
|
|
+
|
|
if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
|
|
dev_info(&pdev->dev, "JMB361 has only one port\n");
|
|
hpriv->force_port_map = 1;
|
|
diff --git drivers/atm/idt77252.c drivers/atm/idt77252.c
|
|
index e7a6b4903f9c..c777973f0ff3 100644
|
|
--- drivers/atm/idt77252.c
|
|
+++ drivers/atm/idt77252.c
|
|
@@ -2933,6 +2933,8 @@ open_card_ubr0(struct idt77252_dev *card)
|
|
vc->scq = alloc_scq(card, vc->class);
|
|
if (!vc->scq) {
|
|
printk("%s: can't get SCQ.\n", card->name);
|
|
+ kfree(card->vcs[0]);
|
|
+ card->vcs[0] = NULL;
|
|
return -ENOMEM;
|
|
}
|
|
|
|
diff --git drivers/base/core.c drivers/base/core.c
|
|
index e834087448a4..4f1ac622df06 100644
|
|
--- drivers/base/core.c
|
|
+++ drivers/base/core.c
|
|
@@ -3075,6 +3075,50 @@ define_dev_printk_level(_dev_info, KERN_INFO);
|
|
|
|
#endif
|
|
|
|
+/**
|
|
+ * dev_err_probe - probe error check and log helper
|
|
+ * @dev: the pointer to the struct device
|
|
+ * @err: error value to test
|
|
+ * @fmt: printf-style format string
|
|
+ * @...: arguments as specified in the format string
|
|
+ *
|
|
+ * This helper implements common pattern present in probe functions for error
|
|
+ * checking: print debug or error message depending if the error value is
|
|
+ * -EPROBE_DEFER and propagate error upwards.
|
|
+ * It replaces code sequence::
|
|
+ * if (err != -EPROBE_DEFER)
|
|
+ * dev_err(dev, ...);
|
|
+ * else
|
|
+ * dev_dbg(dev, ...);
|
|
+ * return err;
|
|
+ *
|
|
+ * with::
|
|
+ *
|
|
+ * return dev_err_probe(dev, err, ...);
|
|
+ *
|
|
+ * Returns @err.
|
|
+ *
|
|
+ */
|
|
+int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
|
|
+{
|
|
+ struct va_format vaf;
|
|
+ va_list args;
|
|
+
|
|
+ va_start(args, fmt);
|
|
+ vaf.fmt = fmt;
|
|
+ vaf.va = &args;
|
|
+
|
|
+ if (err != -EPROBE_DEFER)
|
|
+ dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
|
|
+ else
|
|
+ dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
|
|
+
|
|
+ va_end(args);
|
|
+
|
|
+ return err;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(dev_err_probe);
|
|
+
|
|
static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
|
|
{
|
|
return fwnode && !IS_ERR(fwnode->secondary);
|
|
diff --git drivers/base/power/domain.c drivers/base/power/domain.c
|
|
index 0f38df5856e1..a469fb4badf2 100644
|
|
--- drivers/base/power/domain.c
|
|
+++ drivers/base/power/domain.c
|
|
@@ -749,7 +749,7 @@ static int __init genpd_power_off_unused(void)
|
|
|
|
return 0;
|
|
}
|
|
-late_initcall(genpd_power_off_unused);
|
|
+late_initcall_sync(genpd_power_off_unused);
|
|
|
|
#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_GENERIC_DOMAINS_OF)
|
|
|
|
diff --git drivers/block/virtio_blk.c drivers/block/virtio_blk.c
|
|
index 7e8f58c2f65b..2d3484a83fd7 100644
|
|
--- drivers/block/virtio_blk.c
|
|
+++ drivers/block/virtio_blk.c
|
|
@@ -930,14 +930,15 @@ static int virtblk_freeze(struct virtio_device *vdev)
|
|
{
|
|
struct virtio_blk *vblk = vdev->priv;
|
|
|
|
+ /* Ensure no requests in virtqueues before deleting vqs. */
|
|
+ blk_mq_freeze_queue(vblk->disk->queue);
|
|
+
|
|
/* Ensure we don't receive any more interrupts */
|
|
vdev->config->reset(vdev);
|
|
|
|
/* Make sure no work handler is accessing the device. */
|
|
flush_work(&vblk->config_work);
|
|
|
|
- blk_mq_quiesce_queue(vblk->disk->queue);
|
|
-
|
|
vdev->config->del_vqs(vdev);
|
|
kfree(vblk->vqs);
|
|
|
|
@@ -955,7 +956,7 @@ static int virtblk_restore(struct virtio_device *vdev)
|
|
|
|
virtio_device_ready(vdev);
|
|
|
|
- blk_mq_unquiesce_queue(vblk->disk->queue);
|
|
+ blk_mq_unfreeze_queue(vblk->disk->queue);
|
|
return 0;
|
|
}
|
|
#endif
|
|
diff --git drivers/char/hw_random/core.c drivers/char/hw_random/core.c
|
|
index 303fd55f9be0..a12561fdd2f0 100644
|
|
--- drivers/char/hw_random/core.c
|
|
+++ drivers/char/hw_random/core.c
|
|
@@ -24,10 +24,13 @@
|
|
#include <linux/random.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/slab.h>
|
|
+#include <linux/string.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#define RNG_MODULE_NAME "hw_random"
|
|
|
|
+#define RNG_BUFFER_SIZE (SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES)
|
|
+
|
|
static struct hwrng *current_rng;
|
|
/* the current rng has been explicitly chosen by user via sysfs */
|
|
static int cur_rng_set_by_user;
|
|
@@ -59,7 +62,7 @@ static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
|
|
|
|
static size_t rng_buffer_size(void)
|
|
{
|
|
- return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
|
|
+ return RNG_BUFFER_SIZE;
|
|
}
|
|
|
|
static void add_early_randomness(struct hwrng *rng)
|
|
@@ -202,6 +205,7 @@ static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
|
|
static ssize_t rng_dev_read(struct file *filp, char __user *buf,
|
|
size_t size, loff_t *offp)
|
|
{
|
|
+ u8 buffer[RNG_BUFFER_SIZE];
|
|
ssize_t ret = 0;
|
|
int err = 0;
|
|
int bytes_read, len;
|
|
@@ -229,34 +233,37 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
|
|
if (bytes_read < 0) {
|
|
err = bytes_read;
|
|
goto out_unlock_reading;
|
|
+ } else if (bytes_read == 0 &&
|
|
+ (filp->f_flags & O_NONBLOCK)) {
|
|
+ err = -EAGAIN;
|
|
+ goto out_unlock_reading;
|
|
}
|
|
+
|
|
data_avail = bytes_read;
|
|
}
|
|
|
|
- if (!data_avail) {
|
|
- if (filp->f_flags & O_NONBLOCK) {
|
|
- err = -EAGAIN;
|
|
- goto out_unlock_reading;
|
|
- }
|
|
- } else {
|
|
- len = data_avail;
|
|
+ len = data_avail;
|
|
+ if (len) {
|
|
if (len > size)
|
|
len = size;
|
|
|
|
data_avail -= len;
|
|
|
|
- if (copy_to_user(buf + ret, rng_buffer + data_avail,
|
|
- len)) {
|
|
+ memcpy(buffer, rng_buffer + data_avail, len);
|
|
+ }
|
|
+ mutex_unlock(&reading_mutex);
|
|
+ put_rng(rng);
|
|
+
|
|
+ if (len) {
|
|
+ if (copy_to_user(buf + ret, buffer, len)) {
|
|
err = -EFAULT;
|
|
- goto out_unlock_reading;
|
|
+ goto out;
|
|
}
|
|
|
|
size -= len;
|
|
ret += len;
|
|
}
|
|
|
|
- mutex_unlock(&reading_mutex);
|
|
- put_rng(rng);
|
|
|
|
if (need_resched())
|
|
schedule_timeout_interruptible(1);
|
|
@@ -267,6 +274,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
|
|
}
|
|
}
|
|
out:
|
|
+ memzero_explicit(buffer, sizeof(buffer));
|
|
return ret ? : err;
|
|
|
|
out_unlock_reading:
|
|
diff --git drivers/clk/hisilicon/clk-hi3620.c drivers/clk/hisilicon/clk-hi3620.c
|
|
index fa0fba653898..7f49c7067028 100644
|
|
--- drivers/clk/hisilicon/clk-hi3620.c
|
|
+++ drivers/clk/hisilicon/clk-hi3620.c
|
|
@@ -481,8 +481,10 @@ static void __init hi3620_mmc_clk_init(struct device_node *node)
|
|
return;
|
|
|
|
clk_data->clks = kcalloc(num, sizeof(*clk_data->clks), GFP_KERNEL);
|
|
- if (!clk_data->clks)
|
|
+ if (!clk_data->clks) {
|
|
+ kfree(clk_data);
|
|
return;
|
|
+ }
|
|
|
|
for (i = 0; i < num; i++) {
|
|
struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
|
|
diff --git drivers/clk/mmp/clk-of-pxa168.c drivers/clk/mmp/clk-of-pxa168.c
|
|
index f110c02e83cb..9674c6c06dca 100644
|
|
--- drivers/clk/mmp/clk-of-pxa168.c
|
|
+++ drivers/clk/mmp/clk-of-pxa168.c
|
|
@@ -258,18 +258,21 @@ static void __init pxa168_clk_init(struct device_node *np)
|
|
pxa_unit->mpmu_base = of_iomap(np, 0);
|
|
if (!pxa_unit->mpmu_base) {
|
|
pr_err("failed to map mpmu registers\n");
|
|
+ kfree(pxa_unit);
|
|
return;
|
|
}
|
|
|
|
pxa_unit->apmu_base = of_iomap(np, 1);
|
|
if (!pxa_unit->apmu_base) {
|
|
pr_err("failed to map apmu registers\n");
|
|
+ kfree(pxa_unit);
|
|
return;
|
|
}
|
|
|
|
pxa_unit->apbc_base = of_iomap(np, 2);
|
|
if (!pxa_unit->apbc_base) {
|
|
pr_err("failed to map apbc registers\n");
|
|
+ kfree(pxa_unit);
|
|
return;
|
|
}
|
|
|
|
diff --git drivers/clk/rockchip/clk-rk3128.c drivers/clk/rockchip/clk-rk3128.c
|
|
index 5970a50671b9..83c7eb18321f 100644
|
|
--- drivers/clk/rockchip/clk-rk3128.c
|
|
+++ drivers/clk/rockchip/clk-rk3128.c
|
|
@@ -497,7 +497,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
|
GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
|
|
GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
|
|
GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
|
|
- GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 13, GFLAGS),
|
|
+ GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 13, GFLAGS),
|
|
GATE(0, "hclk_peri_ahb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
|
|
GATE(HCLK_SPDIF, "hclk_spdif", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
|
|
GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 12, GFLAGS),
|
|
diff --git drivers/crypto/ccp/ccp-ops.c drivers/crypto/ccp/ccp-ops.c
|
|
index 453d27d2a4ff..56c571370486 100644
|
|
--- drivers/crypto/ccp/ccp-ops.c
|
|
+++ drivers/crypto/ccp/ccp-ops.c
|
|
@@ -183,8 +183,11 @@ static int ccp_init_dm_workarea(struct ccp_dm_workarea *wa,
|
|
|
|
wa->dma.address = dma_map_single(wa->dev, wa->address, len,
|
|
dir);
|
|
- if (dma_mapping_error(wa->dev, wa->dma.address))
|
|
+ if (dma_mapping_error(wa->dev, wa->dma.address)) {
|
|
+ kfree(wa->address);
|
|
+ wa->address = NULL;
|
|
return -ENOMEM;
|
|
+ }
|
|
|
|
wa->dma.length = len;
|
|
}
|
|
diff --git drivers/crypto/sahara.c drivers/crypto/sahara.c
|
|
index 085c229eab1d..fdc9db6c0d5e 100644
|
|
--- drivers/crypto/sahara.c
|
|
+++ drivers/crypto/sahara.c
|
|
@@ -46,7 +46,6 @@
|
|
#define FLAGS_MODE_MASK 0x000f
|
|
#define FLAGS_ENCRYPT BIT(0)
|
|
#define FLAGS_CBC BIT(1)
|
|
-#define FLAGS_NEW_KEY BIT(3)
|
|
|
|
#define SAHARA_HDR_BASE 0x00800000
|
|
#define SAHARA_HDR_SKHA_ALG_AES 0
|
|
@@ -144,8 +143,6 @@ struct sahara_hw_link {
|
|
};
|
|
|
|
struct sahara_ctx {
|
|
- unsigned long flags;
|
|
-
|
|
/* AES-specific context */
|
|
int keylen;
|
|
u8 key[AES_KEYSIZE_128];
|
|
@@ -448,27 +445,24 @@ static int sahara_hw_descriptor_create(struct sahara_dev *dev)
|
|
int ret;
|
|
int i, j;
|
|
int idx = 0;
|
|
+ u32 len;
|
|
|
|
- /* Copy new key if necessary */
|
|
- if (ctx->flags & FLAGS_NEW_KEY) {
|
|
- memcpy(dev->key_base, ctx->key, ctx->keylen);
|
|
- ctx->flags &= ~FLAGS_NEW_KEY;
|
|
+ memcpy(dev->key_base, ctx->key, ctx->keylen);
|
|
|
|
- if (dev->flags & FLAGS_CBC) {
|
|
- dev->hw_desc[idx]->len1 = AES_BLOCK_SIZE;
|
|
- dev->hw_desc[idx]->p1 = dev->iv_phys_base;
|
|
- } else {
|
|
- dev->hw_desc[idx]->len1 = 0;
|
|
- dev->hw_desc[idx]->p1 = 0;
|
|
- }
|
|
- dev->hw_desc[idx]->len2 = ctx->keylen;
|
|
- dev->hw_desc[idx]->p2 = dev->key_phys_base;
|
|
- dev->hw_desc[idx]->next = dev->hw_phys_desc[1];
|
|
+ if (dev->flags & FLAGS_CBC) {
|
|
+ dev->hw_desc[idx]->len1 = AES_BLOCK_SIZE;
|
|
+ dev->hw_desc[idx]->p1 = dev->iv_phys_base;
|
|
+ } else {
|
|
+ dev->hw_desc[idx]->len1 = 0;
|
|
+ dev->hw_desc[idx]->p1 = 0;
|
|
+ }
|
|
+ dev->hw_desc[idx]->len2 = ctx->keylen;
|
|
+ dev->hw_desc[idx]->p2 = dev->key_phys_base;
|
|
+ dev->hw_desc[idx]->next = dev->hw_phys_desc[1];
|
|
+ dev->hw_desc[idx]->hdr = sahara_aes_key_hdr(dev);
|
|
|
|
- dev->hw_desc[idx]->hdr = sahara_aes_key_hdr(dev);
|
|
+ idx++;
|
|
|
|
- idx++;
|
|
- }
|
|
|
|
dev->nb_in_sg = sg_nents_for_len(dev->in_sg, dev->total);
|
|
if (dev->nb_in_sg < 0) {
|
|
@@ -490,24 +484,27 @@ static int sahara_hw_descriptor_create(struct sahara_dev *dev)
|
|
DMA_TO_DEVICE);
|
|
if (ret != dev->nb_in_sg) {
|
|
dev_err(dev->device, "couldn't map in sg\n");
|
|
- goto unmap_in;
|
|
+ return -EINVAL;
|
|
}
|
|
+
|
|
ret = dma_map_sg(dev->device, dev->out_sg, dev->nb_out_sg,
|
|
DMA_FROM_DEVICE);
|
|
if (ret != dev->nb_out_sg) {
|
|
dev_err(dev->device, "couldn't map out sg\n");
|
|
- goto unmap_out;
|
|
+ goto unmap_in;
|
|
}
|
|
|
|
/* Create input links */
|
|
dev->hw_desc[idx]->p1 = dev->hw_phys_link[0];
|
|
sg = dev->in_sg;
|
|
+ len = dev->total;
|
|
for (i = 0; i < dev->nb_in_sg; i++) {
|
|
- dev->hw_link[i]->len = sg->length;
|
|
+ dev->hw_link[i]->len = min(len, sg->length);
|
|
dev->hw_link[i]->p = sg->dma_address;
|
|
if (i == (dev->nb_in_sg - 1)) {
|
|
dev->hw_link[i]->next = 0;
|
|
} else {
|
|
+ len -= min(len, sg->length);
|
|
dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
|
|
sg = sg_next(sg);
|
|
}
|
|
@@ -516,12 +513,14 @@ static int sahara_hw_descriptor_create(struct sahara_dev *dev)
|
|
/* Create output links */
|
|
dev->hw_desc[idx]->p2 = dev->hw_phys_link[i];
|
|
sg = dev->out_sg;
|
|
+ len = dev->total;
|
|
for (j = i; j < dev->nb_out_sg + i; j++) {
|
|
- dev->hw_link[j]->len = sg->length;
|
|
+ dev->hw_link[j]->len = min(len, sg->length);
|
|
dev->hw_link[j]->p = sg->dma_address;
|
|
if (j == (dev->nb_out_sg + i - 1)) {
|
|
dev->hw_link[j]->next = 0;
|
|
} else {
|
|
+ len -= min(len, sg->length);
|
|
dev->hw_link[j]->next = dev->hw_phys_link[j + 1];
|
|
sg = sg_next(sg);
|
|
}
|
|
@@ -540,9 +539,6 @@ static int sahara_hw_descriptor_create(struct sahara_dev *dev)
|
|
|
|
return 0;
|
|
|
|
-unmap_out:
|
|
- dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg,
|
|
- DMA_FROM_DEVICE);
|
|
unmap_in:
|
|
dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
|
|
DMA_TO_DEVICE);
|
|
@@ -587,16 +583,17 @@ static int sahara_aes_process(struct ablkcipher_request *req)
|
|
|
|
timeout = wait_for_completion_timeout(&dev->dma_completion,
|
|
msecs_to_jiffies(SAHARA_TIMEOUT_MS));
|
|
- if (!timeout) {
|
|
- dev_err(dev->device, "AES timeout\n");
|
|
- return -ETIMEDOUT;
|
|
- }
|
|
|
|
dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg,
|
|
DMA_FROM_DEVICE);
|
|
dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
|
|
DMA_TO_DEVICE);
|
|
|
|
+ if (!timeout) {
|
|
+ dev_err(dev->device, "AES timeout\n");
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -611,7 +608,6 @@ static int sahara_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
|
|
/* SAHARA only supports 128bit keys */
|
|
if (keylen == AES_KEYSIZE_128) {
|
|
memcpy(ctx->key, key, keylen);
|
|
- ctx->flags |= FLAGS_NEW_KEY;
|
|
return 0;
|
|
}
|
|
|
|
@@ -800,6 +796,7 @@ static int sahara_sha_hw_links_create(struct sahara_dev *dev,
|
|
int start)
|
|
{
|
|
struct scatterlist *sg;
|
|
+ unsigned int len;
|
|
unsigned int i;
|
|
int ret;
|
|
|
|
@@ -821,12 +818,14 @@ static int sahara_sha_hw_links_create(struct sahara_dev *dev,
|
|
if (!ret)
|
|
return -EFAULT;
|
|
|
|
+ len = rctx->total;
|
|
for (i = start; i < dev->nb_in_sg + start; i++) {
|
|
- dev->hw_link[i]->len = sg->length;
|
|
+ dev->hw_link[i]->len = min(len, sg->length);
|
|
dev->hw_link[i]->p = sg->dma_address;
|
|
if (i == (dev->nb_in_sg + start - 1)) {
|
|
dev->hw_link[i]->next = 0;
|
|
} else {
|
|
+ len -= min(len, sg->length);
|
|
dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
|
|
sg = sg_next(sg);
|
|
}
|
|
@@ -907,24 +906,6 @@ static int sahara_sha_hw_context_descriptor_create(struct sahara_dev *dev,
|
|
return 0;
|
|
}
|
|
|
|
-static int sahara_walk_and_recalc(struct scatterlist *sg, unsigned int nbytes)
|
|
-{
|
|
- if (!sg || !sg->length)
|
|
- return nbytes;
|
|
-
|
|
- while (nbytes && sg) {
|
|
- if (nbytes <= sg->length) {
|
|
- sg->length = nbytes;
|
|
- sg_mark_end(sg);
|
|
- break;
|
|
- }
|
|
- nbytes -= sg->length;
|
|
- sg = sg_next(sg);
|
|
- }
|
|
-
|
|
- return nbytes;
|
|
-}
|
|
-
|
|
static int sahara_sha_prepare_request(struct ahash_request *req)
|
|
{
|
|
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
|
@@ -961,36 +942,20 @@ static int sahara_sha_prepare_request(struct ahash_request *req)
|
|
hash_later, 0);
|
|
}
|
|
|
|
- /* nbytes should now be multiple of blocksize */
|
|
- req->nbytes = req->nbytes - hash_later;
|
|
-
|
|
- sahara_walk_and_recalc(req->src, req->nbytes);
|
|
-
|
|
+ rctx->total = len - hash_later;
|
|
/* have data from previous operation and current */
|
|
if (rctx->buf_cnt && req->nbytes) {
|
|
sg_init_table(rctx->in_sg_chain, 2);
|
|
sg_set_buf(rctx->in_sg_chain, rctx->rembuf, rctx->buf_cnt);
|
|
-
|
|
sg_chain(rctx->in_sg_chain, 2, req->src);
|
|
-
|
|
- rctx->total = req->nbytes + rctx->buf_cnt;
|
|
rctx->in_sg = rctx->in_sg_chain;
|
|
-
|
|
- req->src = rctx->in_sg_chain;
|
|
/* only data from previous operation */
|
|
} else if (rctx->buf_cnt) {
|
|
- if (req->src)
|
|
- rctx->in_sg = req->src;
|
|
- else
|
|
- rctx->in_sg = rctx->in_sg_chain;
|
|
- /* buf was copied into rembuf above */
|
|
+ rctx->in_sg = rctx->in_sg_chain;
|
|
sg_init_one(rctx->in_sg, rctx->rembuf, rctx->buf_cnt);
|
|
- rctx->total = rctx->buf_cnt;
|
|
/* no data from previous operation */
|
|
} else {
|
|
rctx->in_sg = req->src;
|
|
- rctx->total = req->nbytes;
|
|
- req->src = rctx->in_sg;
|
|
}
|
|
|
|
/* on next call, we only have the remaining data in the buffer */
|
|
@@ -1011,7 +976,10 @@ static int sahara_sha_process(struct ahash_request *req)
|
|
return ret;
|
|
|
|
if (rctx->first) {
|
|
- sahara_sha_hw_data_descriptor_create(dev, rctx, req, 0);
|
|
+ ret = sahara_sha_hw_data_descriptor_create(dev, rctx, req, 0);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
dev->hw_desc[0]->next = 0;
|
|
rctx->first = 0;
|
|
} else {
|
|
@@ -1019,7 +987,10 @@ static int sahara_sha_process(struct ahash_request *req)
|
|
|
|
sahara_sha_hw_context_descriptor_create(dev, rctx, req, 0);
|
|
dev->hw_desc[0]->next = dev->hw_phys_desc[1];
|
|
- sahara_sha_hw_data_descriptor_create(dev, rctx, req, 1);
|
|
+ ret = sahara_sha_hw_data_descriptor_create(dev, rctx, req, 1);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
dev->hw_desc[1]->next = 0;
|
|
}
|
|
|
|
@@ -1032,18 +1003,19 @@ static int sahara_sha_process(struct ahash_request *req)
|
|
|
|
timeout = wait_for_completion_timeout(&dev->dma_completion,
|
|
msecs_to_jiffies(SAHARA_TIMEOUT_MS));
|
|
- if (!timeout) {
|
|
- dev_err(dev->device, "SHA timeout\n");
|
|
- return -ETIMEDOUT;
|
|
- }
|
|
|
|
if (rctx->sg_in_idx)
|
|
dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
|
|
DMA_TO_DEVICE);
|
|
|
|
+ if (!timeout) {
|
|
+ dev_err(dev->device, "SHA timeout\n");
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+
|
|
memcpy(rctx->context, dev->context_base, rctx->context_size);
|
|
|
|
- if (req->result)
|
|
+ if (req->result && rctx->last)
|
|
memcpy(req->result, rctx->context, rctx->digest_size);
|
|
|
|
return 0;
|
|
@@ -1187,8 +1159,7 @@ static int sahara_sha_import(struct ahash_request *req, const void *in)
|
|
static int sahara_sha_cra_init(struct crypto_tfm *tfm)
|
|
{
|
|
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
|
|
- sizeof(struct sahara_sha_reqctx) +
|
|
- SHA_BUFFER_LEN + SHA256_BLOCK_SIZE);
|
|
+ sizeof(struct sahara_sha_reqctx));
|
|
|
|
return 0;
|
|
}
|
|
diff --git drivers/crypto/virtio/virtio_crypto_common.h drivers/crypto/virtio/virtio_crypto_common.h
|
|
index e976539a05d9..d8be210a07ec 100644
|
|
--- drivers/crypto/virtio/virtio_crypto_common.h
|
|
+++ drivers/crypto/virtio/virtio_crypto_common.h
|
|
@@ -22,6 +22,7 @@
|
|
#include <linux/virtio.h>
|
|
#include <linux/crypto.h>
|
|
#include <linux/spinlock.h>
|
|
+#include <linux/interrupt.h>
|
|
#include <crypto/aead.h>
|
|
#include <crypto/aes.h>
|
|
#include <crypto/authenc.h>
|
|
@@ -40,6 +41,7 @@ struct data_queue {
|
|
char name[32];
|
|
|
|
struct crypto_engine *engine;
|
|
+ struct tasklet_struct done_task;
|
|
};
|
|
|
|
struct virtio_crypto {
|
|
diff --git drivers/crypto/virtio/virtio_crypto_core.c drivers/crypto/virtio/virtio_crypto_core.c
|
|
index ff1410a32c2b..e21dd216989f 100644
|
|
--- drivers/crypto/virtio/virtio_crypto_core.c
|
|
+++ drivers/crypto/virtio/virtio_crypto_core.c
|
|
@@ -34,27 +34,28 @@ virtcrypto_clear_request(struct virtio_crypto_request *vc_req)
|
|
}
|
|
}
|
|
|
|
-static void virtcrypto_dataq_callback(struct virtqueue *vq)
|
|
+static void virtcrypto_done_task(unsigned long data)
|
|
{
|
|
- struct virtio_crypto *vcrypto = vq->vdev->priv;
|
|
+ struct data_queue *data_vq = (struct data_queue *)data;
|
|
+ struct virtqueue *vq = data_vq->vq;
|
|
struct virtio_crypto_request *vc_req;
|
|
- unsigned long flags;
|
|
unsigned int len;
|
|
- unsigned int qid = vq->index;
|
|
|
|
- spin_lock_irqsave(&vcrypto->data_vq[qid].lock, flags);
|
|
do {
|
|
virtqueue_disable_cb(vq);
|
|
while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) {
|
|
- spin_unlock_irqrestore(
|
|
- &vcrypto->data_vq[qid].lock, flags);
|
|
if (vc_req->alg_cb)
|
|
vc_req->alg_cb(vc_req, len);
|
|
- spin_lock_irqsave(
|
|
- &vcrypto->data_vq[qid].lock, flags);
|
|
}
|
|
} while (!virtqueue_enable_cb(vq));
|
|
- spin_unlock_irqrestore(&vcrypto->data_vq[qid].lock, flags);
|
|
+}
|
|
+
|
|
+static void virtcrypto_dataq_callback(struct virtqueue *vq)
|
|
+{
|
|
+ struct virtio_crypto *vcrypto = vq->vdev->priv;
|
|
+ struct data_queue *dq = &vcrypto->data_vq[vq->index];
|
|
+
|
|
+ tasklet_schedule(&dq->done_task);
|
|
}
|
|
|
|
static int virtcrypto_find_vqs(struct virtio_crypto *vi)
|
|
@@ -114,6 +115,8 @@ static int virtcrypto_find_vqs(struct virtio_crypto *vi)
|
|
|
|
vi->data_vq[i].engine->cipher_one_request =
|
|
virtio_crypto_ablkcipher_crypt_req;
|
|
+ tasklet_init(&vi->data_vq[i].done_task, virtcrypto_done_task,
|
|
+ (unsigned long)&vi->data_vq[i]);
|
|
}
|
|
|
|
kfree(names);
|
|
@@ -417,11 +420,14 @@ static void virtcrypto_free_unused_reqs(struct virtio_crypto *vcrypto)
|
|
static void virtcrypto_remove(struct virtio_device *vdev)
|
|
{
|
|
struct virtio_crypto *vcrypto = vdev->priv;
|
|
+ int i;
|
|
|
|
dev_info(&vdev->dev, "Start virtcrypto_remove.\n");
|
|
|
|
if (virtcrypto_dev_started(vcrypto))
|
|
virtcrypto_dev_stop(vcrypto);
|
|
+ for (i = 0; i < vcrypto->max_data_queues; i++)
|
|
+ tasklet_kill(&vcrypto->data_vq[i].done_task);
|
|
vdev->config->reset(vdev);
|
|
virtcrypto_free_unused_reqs(vcrypto);
|
|
virtcrypto_clear_crypto_engines(vcrypto);
|
|
diff --git drivers/dma/sh/shdma.h drivers/dma/sh/shdma.h
|
|
index 2c0a969adc9f..35987a35a848 100644
|
|
--- drivers/dma/sh/shdma.h
|
|
+++ drivers/dma/sh/shdma.h
|
|
@@ -29,7 +29,7 @@ struct sh_dmae_chan {
|
|
const struct sh_dmae_slave_config *config; /* Slave DMA configuration */
|
|
int xmit_shift; /* log_2(bytes_per_xfer) */
|
|
void __iomem *base;
|
|
- char dev_id[16]; /* unique name per DMAC of channel */
|
|
+ char dev_id[32]; /* unique name per DMAC of channel */
|
|
int pm_error;
|
|
dma_addr_t slave_addr;
|
|
};
|
|
diff --git drivers/edac/thunderx_edac.c drivers/edac/thunderx_edac.c
|
|
index dfefa39e9351..bc9ecc6c0573 100644
|
|
--- drivers/edac/thunderx_edac.c
|
|
+++ drivers/edac/thunderx_edac.c
|
|
@@ -1154,7 +1154,7 @@ static irqreturn_t thunderx_ocx_com_threaded_isr(int irq, void *irq_id)
|
|
decode_register(other, OCX_OTHER_SIZE,
|
|
ocx_com_errors, ctx->reg_com_int);
|
|
|
|
- strncat(msg, other, OCX_MESSAGE_SIZE);
|
|
+ strlcat(msg, other, OCX_MESSAGE_SIZE);
|
|
|
|
for (lane = 0; lane < OCX_RX_LANES; lane++)
|
|
if (ctx->reg_com_int & BIT(lane)) {
|
|
@@ -1163,12 +1163,12 @@ static irqreturn_t thunderx_ocx_com_threaded_isr(int irq, void *irq_id)
|
|
lane, ctx->reg_lane_int[lane],
|
|
lane, ctx->reg_lane_stat11[lane]);
|
|
|
|
- strncat(msg, other, OCX_MESSAGE_SIZE);
|
|
+ strlcat(msg, other, OCX_MESSAGE_SIZE);
|
|
|
|
decode_register(other, OCX_OTHER_SIZE,
|
|
ocx_lane_errors,
|
|
ctx->reg_lane_int[lane]);
|
|
- strncat(msg, other, OCX_MESSAGE_SIZE);
|
|
+ strlcat(msg, other, OCX_MESSAGE_SIZE);
|
|
}
|
|
|
|
if (ctx->reg_com_int & OCX_COM_INT_CE)
|
|
@@ -1238,7 +1238,7 @@ static irqreturn_t thunderx_ocx_lnk_threaded_isr(int irq, void *irq_id)
|
|
decode_register(other, OCX_OTHER_SIZE,
|
|
ocx_com_link_errors, ctx->reg_com_link_int);
|
|
|
|
- strncat(msg, other, OCX_MESSAGE_SIZE);
|
|
+ strlcat(msg, other, OCX_MESSAGE_SIZE);
|
|
|
|
if (ctx->reg_com_link_int & OCX_COM_LINK_INT_UE)
|
|
edac_device_handle_ue(ocx->edac_dev, 0, 0, msg);
|
|
@@ -1917,7 +1917,7 @@ static irqreturn_t thunderx_l2c_threaded_isr(int irq, void *irq_id)
|
|
|
|
decode_register(other, L2C_OTHER_SIZE, l2_errors, ctx->reg_int);
|
|
|
|
- strncat(msg, other, L2C_MESSAGE_SIZE);
|
|
+ strlcat(msg, other, L2C_MESSAGE_SIZE);
|
|
|
|
if (ctx->reg_int & mask_ue)
|
|
edac_device_handle_ue(l2c->edac_dev, 0, 0, msg);
|
|
diff --git drivers/firewire/core-card.c drivers/firewire/core-card.c
|
|
index 11c634125c7d..0e6f96c0e395 100644
|
|
--- drivers/firewire/core-card.c
|
|
+++ drivers/firewire/core-card.c
|
|
@@ -442,7 +442,23 @@ static void bm_work(struct work_struct *work)
|
|
*/
|
|
card->bm_generation = generation;
|
|
|
|
- if (root_device == NULL) {
|
|
+ if (card->gap_count == 0) {
|
|
+ /*
|
|
+ * If self IDs have inconsistent gap counts, do a
|
|
+ * bus reset ASAP. The config rom read might never
|
|
+ * complete, so don't wait for it. However, still
|
|
+ * send a PHY configuration packet prior to the
|
|
+ * bus reset. The PHY configuration packet might
|
|
+ * fail, but 1394-2008 8.4.5.2 explicitly permits
|
|
+ * it in this case, so it should be safe to try.
|
|
+ */
|
|
+ new_root_id = local_id;
|
|
+ /*
|
|
+ * We must always send a bus reset if the gap count
|
|
+ * is inconsistent, so bypass the 5-reset limit.
|
|
+ */
|
|
+ card->bm_retries = 0;
|
|
+ } else if (root_device == NULL) {
|
|
/*
|
|
* Either link_on is false, or we failed to read the
|
|
* config rom. In either case, pick another root.
|
|
diff --git drivers/firewire/core-device.c drivers/firewire/core-device.c
|
|
index a293b39fd4ce..25c5de074525 100644
|
|
--- drivers/firewire/core-device.c
|
|
+++ drivers/firewire/core-device.c
|
|
@@ -113,10 +113,9 @@ static int textual_leaf_to_string(const u32 *block, char *buf, size_t size)
|
|
* @buf: where to put the string
|
|
* @size: size of @buf, in bytes
|
|
*
|
|
- * The string is taken from a minimal ASCII text descriptor leaf after
|
|
- * the immediate entry with @key. The string is zero-terminated.
|
|
- * An overlong string is silently truncated such that it and the
|
|
- * zero byte fit into @size.
|
|
+ * The string is taken from a minimal ASCII text descriptor leaf just after the entry with the
|
|
+ * @key. The string is zero-terminated. An overlong string is silently truncated such that it
|
|
+ * and the zero byte fit into @size.
|
|
*
|
|
* Returns strlen(buf) or a negative error code.
|
|
*/
|
|
diff --git drivers/firmware/efi/capsule-loader.c drivers/firmware/efi/capsule-loader.c
|
|
index 539825a17959..fa36bbdb9ca7 100644
|
|
--- drivers/firmware/efi/capsule-loader.c
|
|
+++ drivers/firmware/efi/capsule-loader.c
|
|
@@ -287,7 +287,7 @@ static int efi_capsule_open(struct inode *inode, struct file *file)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- cap_info->phys = kzalloc(sizeof(void *), GFP_KERNEL);
|
|
+ cap_info->phys = kzalloc(sizeof(phys_addr_t), GFP_KERNEL);
|
|
if (!cap_info->phys) {
|
|
kfree(cap_info->pages);
|
|
kfree(cap_info);
|
|
diff --git drivers/firmware/ti_sci.c drivers/firmware/ti_sci.c
|
|
index dd677fc4578a..7ac5a8bd05c4 100644
|
|
--- drivers/firmware/ti_sci.c
|
|
+++ drivers/firmware/ti_sci.c
|
|
@@ -184,7 +184,7 @@ static int ti_sci_debugfs_create(struct platform_device *pdev,
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
struct resource *res;
|
|
- char debug_name[50] = "ti_sci_debug@";
|
|
+ char debug_name[50];
|
|
|
|
/* Debug region is optional */
|
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
@@ -201,10 +201,10 @@ static int ti_sci_debugfs_create(struct platform_device *pdev,
|
|
/* Setup NULL termination */
|
|
info->debug_buffer[info->debug_region_size] = 0;
|
|
|
|
- info->d = debugfs_create_file(strncat(debug_name, dev_name(dev),
|
|
- sizeof(debug_name) -
|
|
- sizeof("ti_sci_debug@")),
|
|
- 0444, NULL, info, &ti_sci_debug_fops);
|
|
+ snprintf(debug_name, sizeof(debug_name), "ti_sci_debug@%s",
|
|
+ dev_name(dev));
|
|
+ info->d = debugfs_create_file(debug_name, 0444, NULL, info,
|
|
+ &ti_sci_debug_fops);
|
|
if (IS_ERR(info->d))
|
|
return PTR_ERR(info->d);
|
|
|
|
diff --git drivers/gpio/gpio-74x164.c drivers/gpio/gpio-74x164.c
|
|
index 15a1f4b348c4..4043fe0c8247 100644
|
|
--- drivers/gpio/gpio-74x164.c
|
|
+++ drivers/gpio/gpio-74x164.c
|
|
@@ -133,8 +133,6 @@ static int gen_74x164_probe(struct spi_device *spi)
|
|
if (IS_ERR(chip->gpiod_oe))
|
|
return PTR_ERR(chip->gpiod_oe);
|
|
|
|
- gpiod_set_value_cansleep(chip->gpiod_oe, 1);
|
|
-
|
|
spi_set_drvdata(spi, chip);
|
|
|
|
chip->gpio_chip.label = spi->modalias;
|
|
@@ -159,6 +157,8 @@ static int gen_74x164_probe(struct spi_device *spi)
|
|
goto exit_destroy;
|
|
}
|
|
|
|
+ gpiod_set_value_cansleep(chip->gpiod_oe, 1);
|
|
+
|
|
ret = gpiochip_add_data(&chip->gpio_chip, chip);
|
|
if (!ret)
|
|
return 0;
|
|
diff --git drivers/gpio/gpiolib-acpi.c drivers/gpio/gpiolib-acpi.c
|
|
index 713dc43024c9..a2d00b1ff117 100644
|
|
--- drivers/gpio/gpiolib-acpi.c
|
|
+++ drivers/gpio/gpiolib-acpi.c
|
|
@@ -1476,6 +1476,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = {
|
|
.ignore_wake = "INT33FF:01@0",
|
|
},
|
|
},
|
|
+ {
|
|
+ /*
|
|
+ * Spurious wakeups from TP_ATTN# pin
|
|
+ * Found in BIOS 0.35
|
|
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/3073
|
|
+ */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "GPD"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "G1619-04"),
|
|
+ },
|
|
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
|
|
+ .ignore_wake = "PNP0C50:00@8",
|
|
+ },
|
|
+ },
|
|
{} /* Terminating entry */
|
|
};
|
|
|
|
diff --git drivers/gpu/drm/amd/amdgpu/amdgpu_device.c drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
index 076b22c44122..d7192b2a980c 100644
|
|
--- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
+++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
@@ -701,6 +701,7 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
|
|
return true;
|
|
|
|
fw_ver = *((uint32_t *)adev->pm.fw->data + 69);
|
|
+ release_firmware(adev->pm.fw);
|
|
if (fw_ver < 0x00160e00)
|
|
return true;
|
|
}
|
|
diff --git drivers/gpu/drm/amd/amdgpu/kv_dpm.c drivers/gpu/drm/amd/amdgpu/kv_dpm.c
|
|
index d99fb88341f4..a4c9a326e9f5 100644
|
|
--- drivers/gpu/drm/amd/amdgpu/kv_dpm.c
|
|
+++ drivers/gpu/drm/amd/amdgpu/kv_dpm.c
|
|
@@ -2718,10 +2718,8 @@ static int kv_parse_power_table(struct amdgpu_device *adev)
|
|
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
|
|
&non_clock_info_array->nonClockInfo[non_clock_array_index];
|
|
ps = kzalloc(sizeof(struct kv_ps), GFP_KERNEL);
|
|
- if (ps == NULL) {
|
|
- kfree(adev->pm.dpm.ps);
|
|
+ if (ps == NULL)
|
|
return -ENOMEM;
|
|
- }
|
|
adev->pm.dpm.ps[i].ps_priv = ps;
|
|
k = 0;
|
|
idx = (u8 *)&power_state->v2.clockInfoIndex[0];
|
|
diff --git drivers/gpu/drm/amd/amdgpu/si_dpm.c drivers/gpu/drm/amd/amdgpu/si_dpm.c
|
|
index 288ac692f536..5f80f44f5f67 100644
|
|
--- drivers/gpu/drm/amd/amdgpu/si_dpm.c
|
|
+++ drivers/gpu/drm/amd/amdgpu/si_dpm.c
|
|
@@ -7336,10 +7336,9 @@ static int si_dpm_init(struct amdgpu_device *adev)
|
|
|
|
adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
|
|
kzalloc(4 * sizeof(struct amdgpu_clock_voltage_dependency_entry), GFP_KERNEL);
|
|
- if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
|
|
- amdgpu_free_extended_power_table(adev);
|
|
+ if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries)
|
|
return -ENOMEM;
|
|
- }
|
|
+
|
|
adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
|
|
adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
|
|
adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
|
|
diff --git drivers/gpu/drm/bridge/nxp-ptn3460.c drivers/gpu/drm/bridge/nxp-ptn3460.c
|
|
index d64a3283822a..4ea809891f64 100644
|
|
--- drivers/gpu/drm/bridge/nxp-ptn3460.c
|
|
+++ drivers/gpu/drm/bridge/nxp-ptn3460.c
|
|
@@ -64,13 +64,13 @@ static int ptn3460_read_bytes(struct ptn3460_bridge *ptn_bridge, char addr,
|
|
int ret;
|
|
|
|
ret = i2c_master_send(ptn_bridge->client, &addr, 1);
|
|
- if (ret <= 0) {
|
|
+ if (ret < 0) {
|
|
DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = i2c_master_recv(ptn_bridge->client, buf, len);
|
|
- if (ret <= 0) {
|
|
+ if (ret < 0) {
|
|
DRM_ERROR("Failed to recv i2c data, ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
@@ -88,7 +88,7 @@ static int ptn3460_write_byte(struct ptn3460_bridge *ptn_bridge, char addr,
|
|
buf[1] = val;
|
|
|
|
ret = i2c_master_send(ptn_bridge->client, buf, ARRAY_SIZE(buf));
|
|
- if (ret <= 0) {
|
|
+ if (ret < 0) {
|
|
DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
diff --git drivers/gpu/drm/drm_crtc.c drivers/gpu/drm/drm_crtc.c
|
|
index 5af25ce5bf7c..7e37b439ecae 100644
|
|
--- drivers/gpu/drm/drm_crtc.c
|
|
+++ drivers/gpu/drm/drm_crtc.c
|
|
@@ -556,8 +556,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|
struct drm_mode_set set;
|
|
uint32_t __user *set_connectors_ptr;
|
|
struct drm_modeset_acquire_ctx ctx;
|
|
- int ret;
|
|
- int i;
|
|
+ int ret, i, num_connectors = 0;
|
|
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
return -EINVAL;
|
|
@@ -692,6 +691,7 @@ retry:
|
|
connector->name);
|
|
|
|
connector_set[i] = connector;
|
|
+ num_connectors++;
|
|
}
|
|
}
|
|
|
|
@@ -700,7 +700,7 @@ retry:
|
|
set.y = crtc_req->y;
|
|
set.mode = mode;
|
|
set.connectors = connector_set;
|
|
- set.num_connectors = crtc_req->count_connectors;
|
|
+ set.num_connectors = num_connectors;
|
|
set.fb = fb;
|
|
ret = __drm_mode_set_config_internal(&set, &ctx);
|
|
|
|
@@ -709,7 +709,7 @@ out:
|
|
drm_framebuffer_put(fb);
|
|
|
|
if (connector_set) {
|
|
- for (i = 0; i < crtc_req->count_connectors; i++) {
|
|
+ for (i = 0; i < num_connectors; i++) {
|
|
if (connector_set[i])
|
|
drm_connector_put(connector_set[i]);
|
|
}
|
|
diff --git drivers/gpu/drm/drm_drv.c drivers/gpu/drm/drm_drv.c
|
|
index 340440febf9a..384a060aa8a1 100644
|
|
--- drivers/gpu/drm/drm_drv.c
|
|
+++ drivers/gpu/drm/drm_drv.c
|
|
@@ -812,8 +812,11 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
|
|
goto err_minors;
|
|
}
|
|
|
|
- if (drm_core_check_feature(dev, DRIVER_MODESET))
|
|
- drm_modeset_register_all(dev);
|
|
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
|
+ ret = drm_modeset_register_all(dev);
|
|
+ if (ret)
|
|
+ goto err_unload;
|
|
+ }
|
|
|
|
ret = 0;
|
|
|
|
@@ -825,6 +828,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
|
|
|
|
goto out_unlock;
|
|
|
|
+err_unload:
|
|
+ if (dev->driver->unload)
|
|
+ dev->driver->unload(dev);
|
|
err_minors:
|
|
remove_compat_control_link(dev);
|
|
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
|
|
diff --git drivers/gpu/drm/drm_file.c drivers/gpu/drm/drm_file.c
|
|
index 3cf07f5063ff..8705060c72b4 100644
|
|
--- drivers/gpu/drm/drm_file.c
|
|
+++ drivers/gpu/drm/drm_file.c
|
|
@@ -138,7 +138,7 @@ int drm_open(struct inode *inode, struct file *filp)
|
|
{
|
|
struct drm_device *dev;
|
|
struct drm_minor *minor;
|
|
- int retcode;
|
|
+ int retcode = 0;
|
|
int need_setup = 0;
|
|
|
|
minor = drm_minor_acquire(iminor(inode));
|
|
diff --git drivers/gpu/drm/drm_framebuffer.c drivers/gpu/drm/drm_framebuffer.c
|
|
index af40189cdb60..d6476223a941 100644
|
|
--- drivers/gpu/drm/drm_framebuffer.c
|
|
+++ drivers/gpu/drm/drm_framebuffer.c
|
|
@@ -521,7 +521,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
|
|
struct drm_framebuffer *fb;
|
|
unsigned flags;
|
|
int num_clips;
|
|
- int ret;
|
|
+ int ret = 0;
|
|
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
return -EINVAL;
|
|
diff --git drivers/gpu/drm/drm_mipi_dsi.c drivers/gpu/drm/drm_mipi_dsi.c
|
|
index 6995bee5ad0f..488e8e35c722 100644
|
|
--- drivers/gpu/drm/drm_mipi_dsi.c
|
|
+++ drivers/gpu/drm/drm_mipi_dsi.c
|
|
@@ -305,7 +305,8 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
|
|
{
|
|
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
|
|
|
- mipi_dsi_detach(dsi);
|
|
+ if (dsi->attached)
|
|
+ mipi_dsi_detach(dsi);
|
|
mipi_dsi_device_unregister(dsi);
|
|
|
|
return 0;
|
|
@@ -328,11 +329,18 @@ EXPORT_SYMBOL(mipi_dsi_host_unregister);
|
|
int mipi_dsi_attach(struct mipi_dsi_device *dsi)
|
|
{
|
|
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
|
|
+ int ret;
|
|
|
|
if (!ops || !ops->attach)
|
|
return -ENOSYS;
|
|
|
|
- return ops->attach(dsi->host, dsi);
|
|
+ ret = ops->attach(dsi->host, dsi);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ dsi->attached = true;
|
|
+
|
|
+ return 0;
|
|
}
|
|
EXPORT_SYMBOL(mipi_dsi_attach);
|
|
|
|
@@ -344,9 +352,14 @@ int mipi_dsi_detach(struct mipi_dsi_device *dsi)
|
|
{
|
|
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
|
|
|
|
+ if (WARN_ON(!dsi->attached))
|
|
+ return -EINVAL;
|
|
+
|
|
if (!ops || !ops->detach)
|
|
return -ENOSYS;
|
|
|
|
+ dsi->attached = false;
|
|
+
|
|
return ops->detach(dsi->host, dsi);
|
|
}
|
|
EXPORT_SYMBOL(mipi_dsi_detach);
|
|
diff --git drivers/gpu/drm/drm_plane.c drivers/gpu/drm/drm_plane.c
|
|
index 71186bf90760..5354dedaa608 100644
|
|
--- drivers/gpu/drm/drm_plane.c
|
|
+++ drivers/gpu/drm/drm_plane.c
|
|
@@ -1072,6 +1072,7 @@ retry:
|
|
out:
|
|
if (fb)
|
|
drm_framebuffer_put(fb);
|
|
+ fb = NULL;
|
|
if (crtc->primary->old_fb)
|
|
drm_framebuffer_put(crtc->primary->old_fb);
|
|
crtc->primary->old_fb = NULL;
|
|
diff --git drivers/gpu/drm/exynos/exynos_drm_drv.c drivers/gpu/drm/exynos/exynos_drm_drv.c
|
|
index 82b72425a42f..707b4fdd94a7 100644
|
|
--- drivers/gpu/drm/exynos/exynos_drm_drv.c
|
|
+++ drivers/gpu/drm/exynos/exynos_drm_drv.c
|
|
@@ -407,6 +407,7 @@ err_mode_config_cleanup:
|
|
drm_release_iommu_mapping(drm);
|
|
err_free_private:
|
|
kfree(private);
|
|
+ dev_set_drvdata(dev, NULL);
|
|
err_free_drm:
|
|
drm_dev_unref(drm);
|
|
|
|
@@ -423,6 +424,7 @@ static void exynos_drm_unbind(struct device *dev)
|
|
|
|
exynos_drm_fbdev_fini(drm);
|
|
drm_kms_helper_poll_fini(drm);
|
|
+ drm_atomic_helper_shutdown(drm);
|
|
|
|
component_unbind_all(drm->dev, drm);
|
|
drm_mode_config_cleanup(drm);
|
|
@@ -460,9 +462,18 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
|
|
return 0;
|
|
}
|
|
|
|
+static void exynos_drm_platform_shutdown(struct platform_device *pdev)
|
|
+{
|
|
+ struct drm_device *drm = platform_get_drvdata(pdev);
|
|
+
|
|
+ if (drm)
|
|
+ drm_atomic_helper_shutdown(drm);
|
|
+}
|
|
+
|
|
static struct platform_driver exynos_drm_platform_driver = {
|
|
.probe = exynos_drm_platform_probe,
|
|
.remove = exynos_drm_platform_remove,
|
|
+ .shutdown = exynos_drm_platform_shutdown,
|
|
.driver = {
|
|
.name = "exynos-drm",
|
|
.pm = &exynos_drm_pm_ops,
|
|
diff --git drivers/gpu/drm/exynos/exynos_hdmi.c drivers/gpu/drm/exynos/exynos_hdmi.c
|
|
index 0109ff40b1db..3d79a7af8c86 100644
|
|
--- drivers/gpu/drm/exynos/exynos_hdmi.c
|
|
+++ drivers/gpu/drm/exynos/exynos_hdmi.c
|
|
@@ -1722,6 +1722,8 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
|
|
return ret;
|
|
|
|
crtc = exynos_drm_crtc_get_by_type(drm_dev, EXYNOS_DISPLAY_TYPE_HDMI);
|
|
+ if (IS_ERR(crtc))
|
|
+ return PTR_ERR(crtc);
|
|
crtc->pipe_clk = &hdata->phy_clk;
|
|
|
|
ret = hdmi_create_connector(encoder);
|
|
diff --git drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
|
|
index 47fa2aba1983..de0dac7b5d85 100644
|
|
--- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
|
|
+++ drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
|
|
@@ -284,6 +284,7 @@ static void mdp4_crtc_atomic_disable(struct drm_crtc *crtc,
|
|
{
|
|
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
|
|
struct mdp4_kms *mdp4_kms = get_kms(crtc);
|
|
+ unsigned long flags;
|
|
|
|
DBG("%s", mdp4_crtc->name);
|
|
|
|
@@ -293,6 +294,14 @@ static void mdp4_crtc_atomic_disable(struct drm_crtc *crtc,
|
|
mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err);
|
|
mdp4_disable(mdp4_kms);
|
|
|
|
+ if (crtc->state->event && !crtc->state->active) {
|
|
+ WARN_ON(mdp4_crtc->event);
|
|
+ spin_lock_irqsave(&mdp4_kms->dev->event_lock, flags);
|
|
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
|
|
+ crtc->state->event = NULL;
|
|
+ spin_unlock_irqrestore(&mdp4_kms->dev->event_lock, flags);
|
|
+ }
|
|
+
|
|
mdp4_crtc->enabled = false;
|
|
}
|
|
|
|
diff --git drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
|
|
index 4b571cc6bc70..6597def18627 100644
|
|
--- drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
|
|
+++ drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
|
|
@@ -154,11 +154,17 @@ shadow_fw_init(struct nvkm_bios *bios, const char *name)
|
|
return (void *)fw;
|
|
}
|
|
|
|
+static void
|
|
+shadow_fw_release(void *fw)
|
|
+{
|
|
+ release_firmware(fw);
|
|
+}
|
|
+
|
|
static const struct nvbios_source
|
|
shadow_fw = {
|
|
.name = "firmware",
|
|
.init = shadow_fw_init,
|
|
- .fini = (void(*)(void *))release_firmware,
|
|
+ .fini = shadow_fw_release,
|
|
.read = shadow_fw_read,
|
|
.rw = false,
|
|
};
|
|
diff --git drivers/gpu/drm/radeon/r100.c drivers/gpu/drm/radeon/r100.c
|
|
index a4929372090d..56e13bdd4bd0 100644
|
|
--- drivers/gpu/drm/radeon/r100.c
|
|
+++ drivers/gpu/drm/radeon/r100.c
|
|
@@ -2307,7 +2307,7 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track)
|
|
switch (prim_walk) {
|
|
case 1:
|
|
for (i = 0; i < track->num_arrays; i++) {
|
|
- size = track->arrays[i].esize * track->max_indx * 4;
|
|
+ size = track->arrays[i].esize * track->max_indx * 4UL;
|
|
if (track->arrays[i].robj == NULL) {
|
|
DRM_ERROR("(PW %u) Vertex array %u no buffer "
|
|
"bound\n", prim_walk, i);
|
|
@@ -2326,7 +2326,7 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track)
|
|
break;
|
|
case 2:
|
|
for (i = 0; i < track->num_arrays; i++) {
|
|
- size = track->arrays[i].esize * (nverts - 1) * 4;
|
|
+ size = track->arrays[i].esize * (nverts - 1) * 4UL;
|
|
if (track->arrays[i].robj == NULL) {
|
|
DRM_ERROR("(PW %u) Vertex array %u no buffer "
|
|
"bound\n", prim_walk, i);
|
|
diff --git drivers/gpu/drm/radeon/r600_cs.c drivers/gpu/drm/radeon/r600_cs.c
|
|
index 97fd58e97043..f478d88aea8f 100644
|
|
--- drivers/gpu/drm/radeon/r600_cs.c
|
|
+++ drivers/gpu/drm/radeon/r600_cs.c
|
|
@@ -1278,7 +1278,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
|
|
return -EINVAL;
|
|
}
|
|
tmp = (reg - CB_COLOR0_BASE) / 4;
|
|
- track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
|
|
+ track->cb_color_bo_offset[tmp] = (u64)radeon_get_ib_value(p, idx) << 8;
|
|
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
|
|
track->cb_color_base_last[tmp] = ib[idx];
|
|
track->cb_color_bo[tmp] = reloc->robj;
|
|
@@ -1305,7 +1305,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
|
|
"0x%04X\n", reg);
|
|
return -EINVAL;
|
|
}
|
|
- track->htile_offset = radeon_get_ib_value(p, idx) << 8;
|
|
+ track->htile_offset = (u64)radeon_get_ib_value(p, idx) << 8;
|
|
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
|
|
track->htile_bo = reloc->robj;
|
|
track->db_dirty = true;
|
|
diff --git drivers/gpu/drm/radeon/radeon_display.c drivers/gpu/drm/radeon/radeon_display.c
|
|
index 173439a8c881..620f301737a4 100644
|
|
--- drivers/gpu/drm/radeon/radeon_display.c
|
|
+++ drivers/gpu/drm/radeon/radeon_display.c
|
|
@@ -678,11 +678,16 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
|
|
if (radeon_crtc == NULL)
|
|
return;
|
|
|
|
+ radeon_crtc->flip_queue = alloc_workqueue("radeon-crtc", WQ_HIGHPRI, 0);
|
|
+ if (!radeon_crtc->flip_queue) {
|
|
+ kfree(radeon_crtc);
|
|
+ return;
|
|
+ }
|
|
+
|
|
drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs);
|
|
|
|
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
|
|
radeon_crtc->crtc_id = index;
|
|
- radeon_crtc->flip_queue = alloc_workqueue("radeon-crtc", WQ_HIGHPRI, 0);
|
|
rdev->mode_info.crtcs[index] = radeon_crtc;
|
|
|
|
if (rdev->family >= CHIP_BONAIRE) {
|
|
diff --git drivers/gpu/drm/radeon/radeon_vm.c drivers/gpu/drm/radeon/radeon_vm.c
|
|
index e5c0e635e371..6f2133ff7c2c 100644
|
|
--- drivers/gpu/drm/radeon/radeon_vm.c
|
|
+++ drivers/gpu/drm/radeon/radeon_vm.c
|
|
@@ -1205,13 +1205,17 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
|
|
r = radeon_bo_create(rdev, pd_size, align, true,
|
|
RADEON_GEM_DOMAIN_VRAM, 0, NULL,
|
|
NULL, &vm->page_directory);
|
|
- if (r)
|
|
+ if (r) {
|
|
+ kfree(vm->page_tables);
|
|
+ vm->page_tables = NULL;
|
|
return r;
|
|
-
|
|
+ }
|
|
r = radeon_vm_clear_bo(rdev, vm->page_directory);
|
|
if (r) {
|
|
radeon_bo_unref(&vm->page_directory);
|
|
vm->page_directory = NULL;
|
|
+ kfree(vm->page_tables);
|
|
+ vm->page_tables = NULL;
|
|
return r;
|
|
}
|
|
|
|
diff --git drivers/gpu/drm/radeon/si.c drivers/gpu/drm/radeon/si.c
|
|
index 1144cafea9ac..6dc20e790556 100644
|
|
--- drivers/gpu/drm/radeon/si.c
|
|
+++ drivers/gpu/drm/radeon/si.c
|
|
@@ -3612,6 +3612,10 @@ static int si_cp_start(struct radeon_device *rdev)
|
|
for (i = RADEON_RING_TYPE_GFX_INDEX; i <= CAYMAN_RING_TYPE_CP2_INDEX; ++i) {
|
|
ring = &rdev->ring[i];
|
|
r = radeon_ring_lock(rdev, ring, 2);
|
|
+ if (r) {
|
|
+ DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
|
|
+ return r;
|
|
+ }
|
|
|
|
/* clear the compute context state */
|
|
radeon_ring_write(ring, PACKET3_COMPUTE(PACKET3_CLEAR_STATE, 0));
|
|
diff --git drivers/gpu/drm/radeon/sumo_dpm.c drivers/gpu/drm/radeon/sumo_dpm.c
|
|
index fd4804829e46..258cca4ae59b 100644
|
|
--- drivers/gpu/drm/radeon/sumo_dpm.c
|
|
+++ drivers/gpu/drm/radeon/sumo_dpm.c
|
|
@@ -1493,8 +1493,10 @@ static int sumo_parse_power_table(struct radeon_device *rdev)
|
|
non_clock_array_index = power_state->v2.nonClockInfoIndex;
|
|
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
|
|
&non_clock_info_array->nonClockInfo[non_clock_array_index];
|
|
- if (!rdev->pm.power_state[i].clock_info)
|
|
+ if (!rdev->pm.power_state[i].clock_info) {
|
|
+ kfree(rdev->pm.dpm.ps);
|
|
return -EINVAL;
|
|
+ }
|
|
ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
|
|
if (ps == NULL) {
|
|
kfree(rdev->pm.dpm.ps);
|
|
diff --git drivers/gpu/drm/radeon/trinity_dpm.c drivers/gpu/drm/radeon/trinity_dpm.c
|
|
index 2ef7c4e5e495..8fcb7466bf8c 100644
|
|
--- drivers/gpu/drm/radeon/trinity_dpm.c
|
|
+++ drivers/gpu/drm/radeon/trinity_dpm.c
|
|
@@ -1768,8 +1768,10 @@ static int trinity_parse_power_table(struct radeon_device *rdev)
|
|
non_clock_array_index = power_state->v2.nonClockInfoIndex;
|
|
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
|
|
&non_clock_info_array->nonClockInfo[non_clock_array_index];
|
|
- if (!rdev->pm.power_state[i].clock_info)
|
|
+ if (!rdev->pm.power_state[i].clock_info) {
|
|
+ kfree(rdev->pm.dpm.ps);
|
|
return -EINVAL;
|
|
+ }
|
|
ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
|
|
if (ps == NULL) {
|
|
kfree(rdev->pm.dpm.ps);
|
|
diff --git drivers/hid/hid-apple.c drivers/hid/hid-apple.c
|
|
index 80ecbf14d3c8..8ba8f76c92c0 100644
|
|
--- drivers/hid/hid-apple.c
|
|
+++ drivers/hid/hid-apple.c
|
|
@@ -54,6 +54,12 @@ MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\")
|
|
"(For people who want to keep Windows PC keyboard muscle memory. "
|
|
"[0] = as-is, Mac layout. 1 = swapped, Windows layout.)");
|
|
|
|
+static unsigned int swap_fn_leftctrl;
|
|
+module_param(swap_fn_leftctrl, uint, 0644);
|
|
+MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. "
|
|
+ "(For people who want to keep PC keyboard muscle memory. "
|
|
+ "[0] = as-is, Mac layout, 1 = swapped, PC layout)");
|
|
+
|
|
struct apple_sc {
|
|
unsigned long quirks;
|
|
unsigned int fn_on;
|
|
@@ -67,6 +73,28 @@ struct apple_key_translation {
|
|
u8 flags;
|
|
};
|
|
|
|
+static const struct apple_key_translation apple2021_fn_keys[] = {
|
|
+ { KEY_BACKSPACE, KEY_DELETE },
|
|
+ { KEY_ENTER, KEY_INSERT },
|
|
+ { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
|
|
+ { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
|
|
+ { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
|
|
+ { KEY_F4, KEY_SEARCH, APPLE_FLAG_FKEY },
|
|
+ { KEY_F5, KEY_MICMUTE, APPLE_FLAG_FKEY },
|
|
+ { KEY_F6, KEY_SLEEP, APPLE_FLAG_FKEY },
|
|
+ { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
|
|
+ { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
|
|
+ { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
|
|
+ { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
|
|
+ { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
|
|
+ { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
|
|
+ { KEY_UP, KEY_PAGEUP },
|
|
+ { KEY_DOWN, KEY_PAGEDOWN },
|
|
+ { KEY_LEFT, KEY_HOME },
|
|
+ { KEY_RIGHT, KEY_END },
|
|
+ { }
|
|
+};
|
|
+
|
|
static const struct apple_key_translation macbookair_fn_keys[] = {
|
|
{ KEY_BACKSPACE, KEY_DELETE },
|
|
{ KEY_ENTER, KEY_INSERT },
|
|
@@ -166,6 +194,11 @@ static const struct apple_key_translation swapped_option_cmd_keys[] = {
|
|
{ }
|
|
};
|
|
|
|
+static const struct apple_key_translation swapped_fn_leftctrl_keys[] = {
|
|
+ { KEY_FN, KEY_LEFTCTRL },
|
|
+ { }
|
|
+};
|
|
+
|
|
static const struct apple_key_translation *apple_find_translation(
|
|
const struct apple_key_translation *table, u16 from)
|
|
{
|
|
@@ -187,14 +220,18 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
|
|
bool do_translate;
|
|
u16 code = 0;
|
|
|
|
- if (usage->code == KEY_FN) {
|
|
+ u16 fn_keycode = (swap_fn_leftctrl) ? (KEY_LEFTCTRL) : (KEY_FN);
|
|
+
|
|
+ if (usage->code == fn_keycode) {
|
|
asc->fn_on = !!value;
|
|
- input_event(input, usage->type, usage->code, value);
|
|
+ input_event(input, usage->type, KEY_FN, value);
|
|
return 1;
|
|
}
|
|
|
|
if (fnmode) {
|
|
- if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
|
|
+ if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021)
|
|
+ table = apple2021_fn_keys;
|
|
+ else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
|
|
hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
|
|
table = macbookair_fn_keys;
|
|
else if (hid->product < 0x21d || hid->product >= 0x300)
|
|
@@ -274,6 +311,14 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
|
|
}
|
|
}
|
|
|
|
+ if (swap_fn_leftctrl) {
|
|
+ trans = apple_find_translation(swapped_fn_leftctrl_keys, usage->code);
|
|
+ if (trans) {
|
|
+ input_event(input, usage->type, trans->to, value);
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -344,6 +389,14 @@ static void apple_setup_input(struct input_dev *input)
|
|
|
|
for (trans = apple_iso_keyboard; trans->from; trans++)
|
|
set_bit(trans->to, input->keybit);
|
|
+
|
|
+ for (trans = apple2021_fn_keys; trans->from; trans++)
|
|
+ set_bit(trans->to, input->keybit);
|
|
+
|
|
+ if (swap_fn_leftctrl) {
|
|
+ for (trans = swapped_fn_leftctrl_keys; trans->from; trans++)
|
|
+ set_bit(trans->to, input->keybit);
|
|
+ }
|
|
}
|
|
|
|
static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|
@@ -599,6 +652,10 @@ static const struct hid_device_id apple_devices[] = {
|
|
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
|
|
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
|
|
+ .driver_data = APPLE_HAS_FN },
|
|
+ { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
|
|
+ .driver_data = APPLE_HAS_FN },
|
|
|
|
{ }
|
|
};
|
|
diff --git drivers/hid/hid-core.c drivers/hid/hid-core.c
|
|
index fe3824a6af5c..9bfae325a410 100644
|
|
--- drivers/hid/hid-core.c
|
|
+++ drivers/hid/hid-core.c
|
|
@@ -2063,6 +2063,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|
{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_ANSI) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
|
|
#endif
|
|
#if IS_ENABLED(CONFIG_HID_APPLEIR)
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
|
|
diff --git drivers/hid/hid-ids.h drivers/hid/hid-ids.h
|
|
index 26db838be5a2..1b89c9185c14 100644
|
|
--- drivers/hid/hid-ids.h
|
|
+++ drivers/hid/hid-ids.h
|
|
@@ -172,6 +172,7 @@
|
|
#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241
|
|
#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
|
|
#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243
|
|
+#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c
|
|
|
|
#define USB_VENDOR_ID_ASUS 0x0486
|
|
#define USB_DEVICE_ID_ASUS_T91MT 0x0185
|
|
diff --git drivers/hid/wacom_sys.c drivers/hid/wacom_sys.c
|
|
index 3ca50505c78c..b4c25afb3a36 100644
|
|
--- drivers/hid/wacom_sys.c
|
|
+++ drivers/hid/wacom_sys.c
|
|
@@ -1920,7 +1920,7 @@ static int wacom_allocate_inputs(struct wacom *wacom)
|
|
return 0;
|
|
}
|
|
|
|
-static int wacom_register_inputs(struct wacom *wacom)
|
|
+static int wacom_setup_inputs(struct wacom *wacom)
|
|
{
|
|
struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
|
|
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
|
|
@@ -1939,10 +1939,6 @@ static int wacom_register_inputs(struct wacom *wacom)
|
|
input_free_device(pen_input_dev);
|
|
wacom_wac->pen_input = NULL;
|
|
pen_input_dev = NULL;
|
|
- } else {
|
|
- error = input_register_device(pen_input_dev);
|
|
- if (error)
|
|
- goto fail;
|
|
}
|
|
|
|
error = wacom_setup_touch_input_capabilities(touch_input_dev, wacom_wac);
|
|
@@ -1951,10 +1947,6 @@ static int wacom_register_inputs(struct wacom *wacom)
|
|
input_free_device(touch_input_dev);
|
|
wacom_wac->touch_input = NULL;
|
|
touch_input_dev = NULL;
|
|
- } else {
|
|
- error = input_register_device(touch_input_dev);
|
|
- if (error)
|
|
- goto fail;
|
|
}
|
|
|
|
error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
|
|
@@ -1963,7 +1955,34 @@ static int wacom_register_inputs(struct wacom *wacom)
|
|
input_free_device(pad_input_dev);
|
|
wacom_wac->pad_input = NULL;
|
|
pad_input_dev = NULL;
|
|
- } else {
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int wacom_register_inputs(struct wacom *wacom)
|
|
+{
|
|
+ struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
|
|
+ struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
|
|
+ int error = 0;
|
|
+
|
|
+ pen_input_dev = wacom_wac->pen_input;
|
|
+ touch_input_dev = wacom_wac->touch_input;
|
|
+ pad_input_dev = wacom_wac->pad_input;
|
|
+
|
|
+ if (pen_input_dev) {
|
|
+ error = input_register_device(pen_input_dev);
|
|
+ if (error)
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ if (touch_input_dev) {
|
|
+ error = input_register_device(touch_input_dev);
|
|
+ if (error)
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ if (pad_input_dev) {
|
|
error = input_register_device(pad_input_dev);
|
|
if (error)
|
|
goto fail;
|
|
@@ -2213,6 +2232,20 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
|
|
goto fail;
|
|
}
|
|
|
|
+ error = wacom_setup_inputs(wacom);
|
|
+ if (error)
|
|
+ goto fail;
|
|
+
|
|
+ if (features->type == HID_GENERIC)
|
|
+ connect_mask |= HID_CONNECT_DRIVER;
|
|
+
|
|
+ /* Regular HID work starts now */
|
|
+ error = hid_hw_start(hdev, connect_mask);
|
|
+ if (error) {
|
|
+ hid_err(hdev, "hw start failed\n");
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
error = wacom_register_inputs(wacom);
|
|
if (error)
|
|
goto fail;
|
|
@@ -2227,16 +2260,6 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
|
|
goto fail;
|
|
}
|
|
|
|
- if (features->type == HID_GENERIC)
|
|
- connect_mask |= HID_CONNECT_DRIVER;
|
|
-
|
|
- /* Regular HID work starts now */
|
|
- error = hid_hw_start(hdev, connect_mask);
|
|
- if (error) {
|
|
- hid_err(hdev, "hw start failed\n");
|
|
- goto fail;
|
|
- }
|
|
-
|
|
if (!wireless) {
|
|
/* Note that if query fails it is not a hard failure */
|
|
wacom_query_tablet_data(wacom);
|
|
diff --git drivers/hid/wacom_wac.c drivers/hid/wacom_wac.c
|
|
index 19a798eb395c..eb39c88b5eac 100644
|
|
--- drivers/hid/wacom_wac.c
|
|
+++ drivers/hid/wacom_wac.c
|
|
@@ -2317,7 +2317,14 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
|
|
wacom_wac->hid_data.tipswitch);
|
|
input_report_key(input, wacom_wac->tool[0], prox);
|
|
if (wacom_wac->serial[0]) {
|
|
- input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
|
|
+ /*
|
|
+ * xf86-input-wacom does not accept a serial number
|
|
+ * of '0'. Report the low 32 bits if possible, but
|
|
+ * if they are zero, report the upper ones instead.
|
|
+ */
|
|
+ __u32 serial_lo = wacom_wac->serial[0] & 0xFFFFFFFFu;
|
|
+ __u32 serial_hi = wacom_wac->serial[0] >> 32;
|
|
+ input_event(input, EV_MSC, MSC_SERIAL, (int)(serial_lo ? serial_lo : serial_hi));
|
|
input_report_abs(input, ABS_MISC, prox ? id : 0);
|
|
}
|
|
|
|
@@ -2389,8 +2396,8 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
|
|
{
|
|
struct hid_data *hid_data = &wacom_wac->hid_data;
|
|
bool mt = wacom_wac->features.touch_max > 1;
|
|
- bool prox = hid_data->tipswitch &&
|
|
- report_touch_events(wacom_wac);
|
|
+ bool touch_down = hid_data->tipswitch && hid_data->confidence;
|
|
+ bool prox = touch_down && report_touch_events(wacom_wac);
|
|
|
|
if (wacom_wac->shared->has_mute_touch_switch &&
|
|
!wacom_wac->shared->is_touch_on) {
|
|
@@ -2429,24 +2436,6 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
|
|
}
|
|
}
|
|
|
|
-static bool wacom_wac_slot_is_active(struct input_dev *dev, int key)
|
|
-{
|
|
- struct input_mt *mt = dev->mt;
|
|
- struct input_mt_slot *s;
|
|
-
|
|
- if (!mt)
|
|
- return false;
|
|
-
|
|
- for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
|
|
- if (s->key == key &&
|
|
- input_mt_get_value(s, ABS_MT_TRACKING_ID) >= 0) {
|
|
- return true;
|
|
- }
|
|
- }
|
|
-
|
|
- return false;
|
|
-}
|
|
-
|
|
static void wacom_wac_finger_event(struct hid_device *hdev,
|
|
struct hid_field *field, struct hid_usage *usage, __s32 value)
|
|
{
|
|
@@ -2489,14 +2478,8 @@ static void wacom_wac_finger_event(struct hid_device *hdev,
|
|
|
|
|
|
if (usage->usage_index + 1 == field->report_count) {
|
|
- if (equivalent_usage == wacom_wac->hid_data.last_slot_field) {
|
|
- bool touch_removed = wacom_wac_slot_is_active(wacom_wac->touch_input,
|
|
- wacom_wac->hid_data.id) && !wacom_wac->hid_data.tipswitch;
|
|
-
|
|
- if (wacom_wac->hid_data.confidence || touch_removed) {
|
|
- wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input);
|
|
- }
|
|
- }
|
|
+ if (equivalent_usage == wacom_wac->hid_data.last_slot_field)
|
|
+ wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input);
|
|
}
|
|
}
|
|
|
|
diff --git drivers/hwmon/aspeed-pwm-tacho.c drivers/hwmon/aspeed-pwm-tacho.c
|
|
index e4337e9dda44..922c5930373b 100644
|
|
--- drivers/hwmon/aspeed-pwm-tacho.c
|
|
+++ drivers/hwmon/aspeed-pwm-tacho.c
|
|
@@ -195,6 +195,8 @@ struct aspeed_pwm_tacho_data {
|
|
u8 fan_tach_ch_source[16];
|
|
struct aspeed_cooling_device *cdev[8];
|
|
const struct attribute_group *groups[3];
|
|
+ /* protects access to shared ASPEED_PTCR_RESULT */
|
|
+ struct mutex tach_lock;
|
|
};
|
|
|
|
enum type { TYPEM, TYPEN, TYPEO };
|
|
@@ -529,6 +531,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
|
|
u8 fan_tach_ch_source, type, mode, both;
|
|
int ret;
|
|
|
|
+ mutex_lock(&priv->tach_lock);
|
|
+
|
|
regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
|
|
regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
|
|
|
|
@@ -546,6 +550,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
|
|
ASPEED_RPM_STATUS_SLEEP_USEC,
|
|
usec);
|
|
|
|
+ mutex_unlock(&priv->tach_lock);
|
|
+
|
|
/* return -ETIMEDOUT if we didn't get an answer. */
|
|
if (ret)
|
|
return ret;
|
|
@@ -929,6 +935,7 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
|
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
|
if (!priv)
|
|
return -ENOMEM;
|
|
+ mutex_init(&priv->tach_lock);
|
|
priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
|
|
&aspeed_pwm_tacho_regmap_config);
|
|
if (IS_ERR(priv->regmap))
|
|
diff --git drivers/hwmon/coretemp.c drivers/hwmon/coretemp.c
|
|
index 770bf76a5348..532cc7286cf0 100644
|
|
--- drivers/hwmon/coretemp.c
|
|
+++ drivers/hwmon/coretemp.c
|
|
@@ -53,7 +53,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
|
|
|
|
#define PKG_SYSFS_ATTR_NO 1 /* Sysfs attribute for package temp */
|
|
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
|
|
-#define NUM_REAL_CORES 128 /* Number of Real cores per cpu */
|
|
+#define NUM_REAL_CORES 512 /* Number of Real cores per cpu */
|
|
#define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */
|
|
#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
|
|
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
|
|
diff --git drivers/hwtracing/coresight/coresight-etm4x.h drivers/hwtracing/coresight/coresight-etm4x.h
|
|
index b3b5ea7b7fb3..d48c40d8fc28 100644
|
|
--- drivers/hwtracing/coresight/coresight-etm4x.h
|
|
+++ drivers/hwtracing/coresight/coresight-etm4x.h
|
|
@@ -373,7 +373,7 @@ struct etmv4_drvdata {
|
|
u8 ctxid_size;
|
|
u8 vmid_size;
|
|
u8 ccsize;
|
|
- u8 ccitmin;
|
|
+ u16 ccitmin;
|
|
u8 s_ex_level;
|
|
u8 ns_ex_level;
|
|
u8 q_support;
|
|
diff --git drivers/i2c/busses/i2c-s3c2410.c drivers/i2c/busses/i2c-s3c2410.c
|
|
index 911f8628128e..299d8f388d62 100644
|
|
--- drivers/i2c/busses/i2c-s3c2410.c
|
|
+++ drivers/i2c/busses/i2c-s3c2410.c
|
|
@@ -235,8 +235,17 @@ static bool is_ack(struct s3c24xx_i2c *i2c)
|
|
int tries;
|
|
|
|
for (tries = 50; tries; --tries) {
|
|
- if (readl(i2c->regs + S3C2410_IICCON)
|
|
- & S3C2410_IICCON_IRQPEND) {
|
|
+ unsigned long tmp = readl(i2c->regs + S3C2410_IICCON);
|
|
+
|
|
+ if (!(tmp & S3C2410_IICCON_ACKEN)) {
|
|
+ /*
|
|
+ * Wait a bit for the bus to stabilize,
|
|
+ * delay estimated experimentally.
|
|
+ */
|
|
+ usleep_range(100, 200);
|
|
+ return true;
|
|
+ }
|
|
+ if (tmp & S3C2410_IICCON_IRQPEND) {
|
|
if (!(readl(i2c->regs + S3C2410_IICSTAT)
|
|
& S3C2410_IICSTAT_LASTBIT))
|
|
return true;
|
|
@@ -289,16 +298,6 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
|
|
|
|
stat |= S3C2410_IICSTAT_START;
|
|
writel(stat, i2c->regs + S3C2410_IICSTAT);
|
|
-
|
|
- if (i2c->quirks & QUIRK_POLL) {
|
|
- while ((i2c->msg_num != 0) && is_ack(i2c)) {
|
|
- i2c_s3c_irq_nextbyte(i2c, stat);
|
|
- stat = readl(i2c->regs + S3C2410_IICSTAT);
|
|
-
|
|
- if (stat & S3C2410_IICSTAT_ARBITR)
|
|
- dev_err(i2c->dev, "deal with arbitration loss\n");
|
|
- }
|
|
- }
|
|
}
|
|
|
|
static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
|
|
@@ -705,7 +704,7 @@ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
|
|
static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
|
|
struct i2c_msg *msgs, int num)
|
|
{
|
|
- unsigned long timeout;
|
|
+ unsigned long timeout = 0;
|
|
int ret;
|
|
|
|
if (i2c->suspended)
|
|
@@ -728,16 +727,19 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
|
|
s3c24xx_i2c_message_start(i2c, msgs);
|
|
|
|
if (i2c->quirks & QUIRK_POLL) {
|
|
- ret = i2c->msg_idx;
|
|
+ while ((i2c->msg_num != 0) && is_ack(i2c)) {
|
|
+ unsigned long stat = readl(i2c->regs + S3C2410_IICSTAT);
|
|
|
|
- if (ret != num)
|
|
- dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
|
|
+ i2c_s3c_irq_nextbyte(i2c, stat);
|
|
|
|
- goto out;
|
|
+ stat = readl(i2c->regs + S3C2410_IICSTAT);
|
|
+ if (stat & S3C2410_IICSTAT_ARBITR)
|
|
+ dev_err(i2c->dev, "deal with arbitration loss\n");
|
|
+ }
|
|
+ } else {
|
|
+ timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
|
}
|
|
|
|
- timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
|
-
|
|
ret = i2c->msg_idx;
|
|
|
|
/*
|
|
diff --git drivers/infiniband/hw/hfi1/pio.c drivers/infiniband/hw/hfi1/pio.c
|
|
index 07bf282fd8aa..162f4cb4851a 100644
|
|
--- drivers/infiniband/hw/hfi1/pio.c
|
|
+++ drivers/infiniband/hw/hfi1/pio.c
|
|
@@ -2133,7 +2133,7 @@ int init_credit_return(struct hfi1_devdata *dd)
|
|
"Unable to allocate credit return DMA range for NUMA %d\n",
|
|
i);
|
|
ret = -ENOMEM;
|
|
- goto done;
|
|
+ goto free_cr_base;
|
|
}
|
|
}
|
|
set_dev_node(&dd->pcidev->dev, dd->node);
|
|
@@ -2141,6 +2141,10 @@ int init_credit_return(struct hfi1_devdata *dd)
|
|
ret = 0;
|
|
done:
|
|
return ret;
|
|
+
|
|
+free_cr_base:
|
|
+ free_credit_return(dd);
|
|
+ goto done;
|
|
}
|
|
|
|
void free_credit_return(struct hfi1_devdata *dd)
|
|
diff --git drivers/infiniband/hw/mthca/mthca_cmd.c drivers/infiniband/hw/mthca/mthca_cmd.c
|
|
index 419a2a20c047..7df5155cdb48 100644
|
|
--- drivers/infiniband/hw/mthca/mthca_cmd.c
|
|
+++ drivers/infiniband/hw/mthca/mthca_cmd.c
|
|
@@ -641,7 +641,7 @@ void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox)
|
|
|
|
int mthca_SYS_EN(struct mthca_dev *dev)
|
|
{
|
|
- u64 out;
|
|
+ u64 out = 0;
|
|
int ret;
|
|
|
|
ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D);
|
|
@@ -1961,7 +1961,7 @@ int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
|
|
int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
|
|
u16 *hash)
|
|
{
|
|
- u64 imm;
|
|
+ u64 imm = 0;
|
|
int err;
|
|
|
|
err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH,
|
|
diff --git drivers/infiniband/hw/mthca/mthca_main.c drivers/infiniband/hw/mthca/mthca_main.c
|
|
index ccf50dafce9c..66a85f757a2f 100644
|
|
--- drivers/infiniband/hw/mthca/mthca_main.c
|
|
+++ drivers/infiniband/hw/mthca/mthca_main.c
|
|
@@ -382,7 +382,7 @@ static int mthca_init_icm(struct mthca_dev *mdev,
|
|
struct mthca_init_hca_param *init_hca,
|
|
u64 icm_size)
|
|
{
|
|
- u64 aux_pages;
|
|
+ u64 aux_pages = 0;
|
|
int err;
|
|
|
|
err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages);
|
|
diff --git drivers/infiniband/ulp/ipoib/ipoib_multicast.c drivers/infiniband/ulp/ipoib/ipoib_multicast.c
|
|
index 9b3f47ae2016..25d7d9219591 100644
|
|
--- drivers/infiniband/ulp/ipoib/ipoib_multicast.c
|
|
+++ drivers/infiniband/ulp/ipoib/ipoib_multicast.c
|
|
@@ -543,21 +543,18 @@ static int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
|
|
/* SM supports sendonly-fullmember, otherwise fallback to full-member */
|
|
rec.join_state = SENDONLY_FULLMEMBER_JOIN;
|
|
}
|
|
- spin_unlock_irq(&priv->lock);
|
|
|
|
multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
|
|
- &rec, comp_mask, GFP_KERNEL,
|
|
+ &rec, comp_mask, GFP_ATOMIC,
|
|
ipoib_mcast_join_complete, mcast);
|
|
- spin_lock_irq(&priv->lock);
|
|
if (IS_ERR(multicast)) {
|
|
ret = PTR_ERR(multicast);
|
|
ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
|
|
/* Requeue this join task with a backoff delay */
|
|
__ipoib_mcast_schedule_join_thread(priv, mcast, 1);
|
|
clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
|
|
- spin_unlock_irq(&priv->lock);
|
|
complete(&mcast->done);
|
|
- spin_lock_irq(&priv->lock);
|
|
+ return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git drivers/infiniband/ulp/srpt/ib_srpt.c drivers/infiniband/ulp/srpt/ib_srpt.c
|
|
index 1446e1cc69ae..08343e6116d2 100644
|
|
--- drivers/infiniband/ulp/srpt/ib_srpt.c
|
|
+++ drivers/infiniband/ulp/srpt/ib_srpt.c
|
|
@@ -80,12 +80,16 @@ module_param(srpt_srq_size, int, 0444);
|
|
MODULE_PARM_DESC(srpt_srq_size,
|
|
"Shared receive queue (SRQ) size.");
|
|
|
|
+static int srpt_set_u64_x(const char *buffer, struct kernel_param *kp)
|
|
+{
|
|
+ return kstrtou64(buffer, 16, (u64 *)kp->arg);
|
|
+}
|
|
static int srpt_get_u64_x(char *buffer, struct kernel_param *kp)
|
|
{
|
|
return sprintf(buffer, "0x%016llx", *(u64 *)kp->arg);
|
|
}
|
|
-module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid,
|
|
- 0444);
|
|
+module_param_call(srpt_service_guid, srpt_set_u64_x, srpt_get_u64_x,
|
|
+ &srpt_service_guid, 0444);
|
|
MODULE_PARM_DESC(srpt_service_guid,
|
|
"Using this value for ioc_guid, id_ext, and cm_listen_id"
|
|
" instead of using the node_guid of the first HCA.");
|
|
@@ -196,8 +200,10 @@ static const char *get_ch_state_name(enum rdma_ch_state s)
|
|
/**
|
|
* srpt_qp_event() - QP event callback function.
|
|
*/
|
|
-static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
|
|
+static void srpt_qp_event(struct ib_event *event, void *ptr)
|
|
{
|
|
+ struct srpt_rdma_ch *ch = ptr;
|
|
+
|
|
pr_debug("QP event %d on cm_id=%p sess_name=%s state=%d\n",
|
|
event->event, ch->cm_id, ch->sess_name, ch->state);
|
|
|
|
@@ -1663,8 +1669,7 @@ retry:
|
|
}
|
|
|
|
qp_init->qp_context = (void *)ch;
|
|
- qp_init->event_handler
|
|
- = (void(*)(struct ib_event *, void*))srpt_qp_event;
|
|
+ qp_init->event_handler = srpt_qp_event;
|
|
qp_init->send_cq = ch->cq;
|
|
qp_init->recv_cq = ch->cq;
|
|
qp_init->srq = sdev->srq;
|
|
diff --git drivers/input/joystick/xpad.c drivers/input/joystick/xpad.c
|
|
index 1dbe30335458..3fedc3688e8f 100644
|
|
--- drivers/input/joystick/xpad.c
|
|
+++ drivers/input/joystick/xpad.c
|
|
@@ -282,6 +282,7 @@ static const struct xpad_device {
|
|
{ 0x146b, 0x0604, "Bigben Interactive DAIJA Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
|
{ 0x1532, 0x0a00, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
|
|
{ 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE },
|
|
+ { 0x1532, 0x0a29, "Razer Wolverine V2", 0, XTYPE_XBOXONE },
|
|
{ 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 },
|
|
{ 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
|
|
{ 0x15e4, 0x3f10, "Batarang Xbox 360 controller", 0, XTYPE_XBOX360 },
|
|
diff --git drivers/input/keyboard/atkbd.c drivers/input/keyboard/atkbd.c
|
|
index 7e75835e220f..585bf7392539 100644
|
|
--- drivers/input/keyboard/atkbd.c
|
|
+++ drivers/input/keyboard/atkbd.c
|
|
@@ -717,6 +717,44 @@ static void atkbd_deactivate(struct atkbd *atkbd)
|
|
ps2dev->serio->phys);
|
|
}
|
|
|
|
+#ifdef CONFIG_X86
|
|
+static bool atkbd_is_portable_device(void)
|
|
+{
|
|
+ static const char * const chassis_types[] = {
|
|
+ "8", /* Portable */
|
|
+ "9", /* Laptop */
|
|
+ "10", /* Notebook */
|
|
+ "14", /* Sub-Notebook */
|
|
+ "31", /* Convertible */
|
|
+ "32", /* Detachable */
|
|
+ };
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(chassis_types); i++)
|
|
+ if (dmi_match(DMI_CHASSIS_TYPE, chassis_types[i]))
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * On many modern laptops ATKBD_CMD_GETID may cause problems, on these laptops
|
|
+ * the controller is always in translated mode. In this mode mice/touchpads will
|
|
+ * not work. So in this case simply assume a keyboard is connected to avoid
|
|
+ * confusing some laptop keyboards.
|
|
+ *
|
|
+ * Skipping ATKBD_CMD_GETID ends up using a fake keyboard id. Using the standard
|
|
+ * 0xab83 id is ok in translated mode, only atkbd_select_set() checks atkbd->id
|
|
+ * and in translated mode that is a no-op.
|
|
+ */
|
|
+static bool atkbd_skip_getid(struct atkbd *atkbd)
|
|
+{
|
|
+ return atkbd->translated && atkbd_is_portable_device();
|
|
+}
|
|
+#else
|
|
+static inline bool atkbd_skip_getid(struct atkbd *atkbd) { return false; }
|
|
+#endif
|
|
+
|
|
/*
|
|
* atkbd_probe() probes for an AT keyboard on a serio port.
|
|
*/
|
|
@@ -738,6 +776,11 @@ static int atkbd_probe(struct atkbd *atkbd)
|
|
"keyboard reset failed on %s\n",
|
|
ps2dev->serio->phys);
|
|
|
|
+ if (atkbd_skip_getid(atkbd)) {
|
|
+ atkbd->id = 0xab83;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
/*
|
|
* Then we check the keyboard ID. We should get 0xab83 under normal conditions.
|
|
* Some keyboards report different values, but the first byte is always 0xab or
|
|
@@ -749,9 +792,9 @@ static int atkbd_probe(struct atkbd *atkbd)
|
|
if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
|
|
|
|
/*
|
|
- * If the get ID command failed, we check if we can at least set the LEDs on
|
|
- * the keyboard. This should work on every keyboard out there. It also turns
|
|
- * the LEDs off, which we want anyway.
|
|
+ * If the get ID command failed, we check if we can at least set
|
|
+ * the LEDs on the keyboard. This should work on every keyboard out there.
|
|
+ * It also turns the LEDs off, which we want anyway.
|
|
*/
|
|
param[0] = 0;
|
|
if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
|
|
diff --git drivers/irqchip/irq-brcmstb-l2.c drivers/irqchip/irq-brcmstb-l2.c
|
|
index b009b916a292..da8a426e9def 100644
|
|
--- drivers/irqchip/irq-brcmstb-l2.c
|
|
+++ drivers/irqchip/irq-brcmstb-l2.c
|
|
@@ -76,6 +76,9 @@ static void brcmstb_l2_intc_irq_handle(struct irq_desc *desc)
|
|
generic_handle_irq(irq_find_mapping(b->domain, irq));
|
|
} while (status);
|
|
out:
|
|
+ /* Don't ack parent before all device writes are done */
|
|
+ wmb();
|
|
+
|
|
chained_irq_exit(chip, desc);
|
|
}
|
|
|
|
diff --git drivers/leds/trigger/ledtrig-panic.c drivers/leds/trigger/ledtrig-panic.c
|
|
index d735526b9db4..2fc04418a87e 100644
|
|
--- drivers/leds/trigger/ledtrig-panic.c
|
|
+++ drivers/leds/trigger/ledtrig-panic.c
|
|
@@ -67,10 +67,13 @@ static long led_panic_blink(int state)
|
|
|
|
static int __init ledtrig_panic_init(void)
|
|
{
|
|
+ led_trigger_register_simple("panic", &trigger);
|
|
+ if (!trigger)
|
|
+ return -ENOMEM;
|
|
+
|
|
atomic_notifier_chain_register(&panic_notifier_list,
|
|
&led_trigger_panic_nb);
|
|
|
|
- led_trigger_register_simple("panic", &trigger);
|
|
panic_blink = led_panic_blink;
|
|
return 0;
|
|
}
|
|
diff --git drivers/md/dm-crypt.c drivers/md/dm-crypt.c
|
|
index 7cc4281d5a79..966fb898f4b8 100644
|
|
--- drivers/md/dm-crypt.c
|
|
+++ drivers/md/dm-crypt.c
|
|
@@ -1742,6 +1742,12 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
|
|
io->ctx.bio_out = clone;
|
|
io->ctx.iter_out = clone->bi_iter;
|
|
|
|
+ if (crypt_integrity_aead(cc)) {
|
|
+ bio_copy_data(clone, io->base_bio);
|
|
+ io->ctx.bio_in = clone;
|
|
+ io->ctx.iter_in = clone->bi_iter;
|
|
+ }
|
|
+
|
|
sector += bio_sectors(clone);
|
|
|
|
crypt_inc_pending(io);
|
|
diff --git drivers/md/md.c drivers/md/md.c
|
|
index 3c2364d0d88f..07da8d7569b5 100644
|
|
--- drivers/md/md.c
|
|
+++ drivers/md/md.c
|
|
@@ -1018,6 +1018,7 @@ struct super_type {
|
|
struct md_rdev *refdev,
|
|
int minor_version);
|
|
int (*validate_super)(struct mddev *mddev,
|
|
+ struct md_rdev *freshest,
|
|
struct md_rdev *rdev);
|
|
void (*sync_super)(struct mddev *mddev,
|
|
struct md_rdev *rdev);
|
|
@@ -1144,8 +1145,9 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
|
|
|
|
/*
|
|
* validate_super for 0.90.0
|
|
+ * note: we are not using "freshest" for 0.9 superblock
|
|
*/
|
|
-static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
|
|
+static int super_90_validate(struct mddev *mddev, struct md_rdev *freshest, struct md_rdev *rdev)
|
|
{
|
|
mdp_disk_t *desc;
|
|
mdp_super_t *sb = page_address(rdev->sb_page);
|
|
@@ -1649,7 +1651,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
|
|
return ret;
|
|
}
|
|
|
|
-static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
|
+static int super_1_validate(struct mddev *mddev, struct md_rdev *freshest, struct md_rdev *rdev)
|
|
{
|
|
struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
|
|
__u64 ev1 = le64_to_cpu(sb->events);
|
|
@@ -1745,13 +1747,15 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
|
}
|
|
} else if (mddev->pers == NULL) {
|
|
/* Insist of good event counter while assembling, except for
|
|
- * spares (which don't need an event count) */
|
|
- ++ev1;
|
|
+ * spares (which don't need an event count).
|
|
+ * Similar to mdadm, we allow event counter difference of 1
|
|
+ * from the freshest device.
|
|
+ */
|
|
if (rdev->desc_nr >= 0 &&
|
|
rdev->desc_nr < le32_to_cpu(sb->max_dev) &&
|
|
(le16_to_cpu(sb->dev_roles[rdev->desc_nr]) < MD_DISK_ROLE_MAX ||
|
|
le16_to_cpu(sb->dev_roles[rdev->desc_nr]) == MD_DISK_ROLE_JOURNAL))
|
|
- if (ev1 < mddev->events)
|
|
+ if (ev1 + 1 < mddev->events)
|
|
return -EINVAL;
|
|
} else if (mddev->bitmap) {
|
|
/* If adding to array with a bitmap, then we can accept an
|
|
@@ -1772,8 +1776,38 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
|
rdev->desc_nr >= le32_to_cpu(sb->max_dev)) {
|
|
role = MD_DISK_ROLE_SPARE;
|
|
rdev->desc_nr = -1;
|
|
- } else
|
|
+ } else if (mddev->pers == NULL && freshest && ev1 < mddev->events) {
|
|
+ /*
|
|
+ * If we are assembling, and our event counter is smaller than the
|
|
+ * highest event counter, we cannot trust our superblock about the role.
|
|
+ * It could happen that our rdev was marked as Faulty, and all other
|
|
+ * superblocks were updated with +1 event counter.
|
|
+ * Then, before the next superblock update, which typically happens when
|
|
+ * remove_and_add_spares() removes the device from the array, there was
|
|
+ * a crash or reboot.
|
|
+ * If we allow current rdev without consulting the freshest superblock,
|
|
+ * we could cause data corruption.
|
|
+ * Note that in this case our event counter is smaller by 1 than the
|
|
+ * highest, otherwise, this rdev would not be allowed into array;
|
|
+ * both kernel and mdadm allow event counter difference of 1.
|
|
+ */
|
|
+ struct mdp_superblock_1 *freshest_sb = page_address(freshest->sb_page);
|
|
+ u32 freshest_max_dev = le32_to_cpu(freshest_sb->max_dev);
|
|
+
|
|
+ if (rdev->desc_nr >= freshest_max_dev) {
|
|
+ /* this is unexpected, better not proceed */
|
|
+ pr_warn("md: %s: rdev[%pg]: desc_nr(%d) >= freshest(%pg)->sb->max_dev(%u)\n",
|
|
+ mdname(mddev), rdev->bdev, rdev->desc_nr,
|
|
+ freshest->bdev, freshest_max_dev);
|
|
+ return -EUCLEAN;
|
|
+ }
|
|
+
|
|
+ role = le16_to_cpu(freshest_sb->dev_roles[rdev->desc_nr]);
|
|
+ pr_debug("md: %s: rdev[%pg]: role=%d(0x%x) according to freshest %pg\n",
|
|
+ mdname(mddev), rdev->bdev, role, role, freshest->bdev);
|
|
+ } else {
|
|
role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
|
|
+ }
|
|
switch(role) {
|
|
case MD_DISK_ROLE_SPARE: /* spare */
|
|
break;
|
|
@@ -2667,7 +2701,7 @@ static int add_bound_rdev(struct md_rdev *rdev)
|
|
* and should be added immediately.
|
|
*/
|
|
super_types[mddev->major_version].
|
|
- validate_super(mddev, rdev);
|
|
+ validate_super(mddev, NULL/*freshest*/, rdev);
|
|
if (add_journal)
|
|
mddev_suspend(mddev);
|
|
err = mddev->pers->hot_add_disk(mddev, rdev);
|
|
@@ -3569,7 +3603,7 @@ static void analyze_sbs(struct mddev *mddev)
|
|
}
|
|
|
|
super_types[mddev->major_version].
|
|
- validate_super(mddev, freshest);
|
|
+ validate_super(mddev, NULL/*freshest*/, freshest);
|
|
|
|
i = 0;
|
|
rdev_for_each_safe(rdev, tmp, mddev) {
|
|
@@ -3584,7 +3618,7 @@ static void analyze_sbs(struct mddev *mddev)
|
|
}
|
|
if (rdev != freshest) {
|
|
if (super_types[mddev->major_version].
|
|
- validate_super(mddev, rdev)) {
|
|
+ validate_super(mddev, freshest, rdev)) {
|
|
pr_warn("md: kicking non-fresh %s from array!\n",
|
|
bdevname(rdev->bdev,b));
|
|
md_kick_rdev_from_array(rdev);
|
|
@@ -6424,7 +6458,7 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
|
|
rdev->saved_raid_disk = rdev->raid_disk;
|
|
} else
|
|
super_types[mddev->major_version].
|
|
- validate_super(mddev, rdev);
|
|
+ validate_super(mddev, NULL/*freshest*/, rdev);
|
|
if ((info->state & (1<<MD_DISK_SYNC)) &&
|
|
rdev->raid_disk != info->raid_disk) {
|
|
/* This was a hot-add request, but events doesn't
|
|
diff --git drivers/md/raid5.c drivers/md/raid5.c
|
|
index d2ac3d189410..6fca2df66550 100644
|
|
--- drivers/md/raid5.c
|
|
+++ drivers/md/raid5.c
|
|
@@ -44,7 +44,6 @@
|
|
*/
|
|
|
|
#include <linux/blkdev.h>
|
|
-#include <linux/delay.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/raid/pq.h>
|
|
#include <linux/async_tx.h>
|
|
@@ -6309,18 +6308,7 @@ static void raid5d(struct md_thread *thread)
|
|
spin_unlock_irq(&conf->device_lock);
|
|
md_check_recovery(mddev);
|
|
spin_lock_irq(&conf->device_lock);
|
|
-
|
|
- /*
|
|
- * Waiting on MD_SB_CHANGE_PENDING below may deadlock
|
|
- * seeing md_check_recovery() is needed to clear
|
|
- * the flag when using mdmon.
|
|
- */
|
|
- continue;
|
|
}
|
|
-
|
|
- wait_event_lock_irq(mddev->sb_wait,
|
|
- !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags),
|
|
- conf->device_lock);
|
|
}
|
|
pr_debug("%d stripes handled\n", handled);
|
|
|
|
diff --git drivers/media/dvb-core/dvbdev.c drivers/media/dvb-core/dvbdev.c
|
|
index 1b3a54520d68..0506179a7c86 100644
|
|
--- drivers/media/dvb-core/dvbdev.c
|
|
+++ drivers/media/dvb-core/dvbdev.c
|
|
@@ -90,6 +90,8 @@ static int dvb_device_open(struct inode *inode, struct file *file)
|
|
err = file->f_op->open(inode, file);
|
|
up_read(&minor_rwsem);
|
|
mutex_unlock(&dvbdev_mutex);
|
|
+ if (err)
|
|
+ dvb_device_put(dvbdev);
|
|
return err;
|
|
}
|
|
fail:
|
|
diff --git drivers/media/pci/ddbridge/ddbridge-main.c drivers/media/pci/ddbridge/ddbridge-main.c
|
|
index ccac7fe31336..13aab32f8048 100644
|
|
--- drivers/media/pci/ddbridge/ddbridge-main.c
|
|
+++ drivers/media/pci/ddbridge/ddbridge-main.c
|
|
@@ -265,7 +265,7 @@ fail:
|
|
ddb_unmap(dev);
|
|
pci_set_drvdata(pdev, NULL);
|
|
pci_disable_device(pdev);
|
|
- return -1;
|
|
+ return stat;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
diff --git drivers/media/usb/cx231xx/cx231xx-core.c drivers/media/usb/cx231xx/cx231xx-core.c
|
|
index f372ad3917a8..61fd934c0205 100644
|
|
--- drivers/media/usb/cx231xx/cx231xx-core.c
|
|
+++ drivers/media/usb/cx231xx/cx231xx-core.c
|
|
@@ -1038,6 +1038,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
|
|
if (!dev->video_mode.isoc_ctl.urb) {
|
|
dev_err(dev->dev,
|
|
"cannot alloc memory for usb buffers\n");
|
|
+ kfree(dma_q->p_left_data);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -1047,6 +1048,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
|
|
dev_err(dev->dev,
|
|
"cannot allocate memory for usbtransfer\n");
|
|
kfree(dev->video_mode.isoc_ctl.urb);
|
|
+ kfree(dma_q->p_left_data);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
diff --git drivers/media/usb/pvrusb2/pvrusb2-context.c drivers/media/usb/pvrusb2/pvrusb2-context.c
|
|
index d9e8481e9e28..9236463ba269 100644
|
|
--- drivers/media/usb/pvrusb2/pvrusb2-context.c
|
|
+++ drivers/media/usb/pvrusb2/pvrusb2-context.c
|
|
@@ -277,7 +277,8 @@ void pvr2_context_disconnect(struct pvr2_context *mp)
|
|
{
|
|
pvr2_hdw_disconnect(mp->hdw);
|
|
mp->disconnect_flag = !0;
|
|
- pvr2_context_notify(mp);
|
|
+ if (!pvr2_context_shutok())
|
|
+ pvr2_context_notify(mp);
|
|
}
|
|
|
|
|
|
diff --git drivers/media/usb/stk1160/stk1160-video.c drivers/media/usb/stk1160/stk1160-video.c
|
|
index ce8ebbe395a6..8a6cdbc36a08 100644
|
|
--- drivers/media/usb/stk1160/stk1160-video.c
|
|
+++ drivers/media/usb/stk1160/stk1160-video.c
|
|
@@ -117,8 +117,7 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
|
|
|
|
/*
|
|
* TODO: These stk1160_dbg are very spammy!
|
|
- * We should 1) check why we are getting them
|
|
- * and 2) add ratelimit.
|
|
+ * We should check why we are getting them.
|
|
*
|
|
* UPDATE: One of the reasons (the only one?) for getting these
|
|
* is incorrect standard (mismatch between expected and configured).
|
|
@@ -161,7 +160,7 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
|
|
|
|
/* Let the bug hunt begin! sanity checks! */
|
|
if (lencopy < 0) {
|
|
- stk1160_dbg("copy skipped: negative lencopy\n");
|
|
+ printk_ratelimited(KERN_DEBUG "copy skipped: negative lencopy\n");
|
|
return;
|
|
}
|
|
|
|
diff --git drivers/mfd/Kconfig drivers/mfd/Kconfig
|
|
index fc5e4fef89d2..7e90ed8fdb1c 100644
|
|
--- drivers/mfd/Kconfig
|
|
+++ drivers/mfd/Kconfig
|
|
@@ -1199,6 +1199,7 @@ config MFD_DAVINCI_VOICECODEC
|
|
|
|
config MFD_TI_AM335X_TSCADC
|
|
tristate "TI ADC / Touch Screen chip support"
|
|
+ depends on ARCH_OMAP2PLUS || ARCH_K3 || COMPILE_TEST
|
|
select MFD_CORE
|
|
select REGMAP
|
|
select REGMAP_MMIO
|
|
diff --git drivers/mmc/core/mmc.c drivers/mmc/core/mmc.c
|
|
index 32bf0b47e339..69f0cc3a28bc 100644
|
|
--- drivers/mmc/core/mmc.c
|
|
+++ drivers/mmc/core/mmc.c
|
|
@@ -990,10 +990,12 @@ static int mmc_select_bus_width(struct mmc_card *card)
|
|
static unsigned ext_csd_bits[] = {
|
|
EXT_CSD_BUS_WIDTH_8,
|
|
EXT_CSD_BUS_WIDTH_4,
|
|
+ EXT_CSD_BUS_WIDTH_1,
|
|
};
|
|
static unsigned bus_widths[] = {
|
|
MMC_BUS_WIDTH_8,
|
|
MMC_BUS_WIDTH_4,
|
|
+ MMC_BUS_WIDTH_1,
|
|
};
|
|
struct mmc_host *host = card->host;
|
|
unsigned idx, bus_width = 0;
|
|
diff --git drivers/mtd/mtd_blkdevs.c drivers/mtd/mtd_blkdevs.c
|
|
index 9ec8f033ac5f..5a76e7c549ef 100644
|
|
--- drivers/mtd/mtd_blkdevs.c
|
|
+++ drivers/mtd/mtd_blkdevs.c
|
|
@@ -513,7 +513,7 @@ static void blktrans_notify_add(struct mtd_info *mtd)
|
|
{
|
|
struct mtd_blktrans_ops *tr;
|
|
|
|
- if (mtd->type == MTD_ABSENT)
|
|
+ if (mtd->type == MTD_ABSENT || mtd->type == MTD_UBIVOLUME)
|
|
return;
|
|
|
|
list_for_each_entry(tr, &blktrans_majors, list)
|
|
@@ -556,7 +556,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
|
|
list_add(&tr->list, &blktrans_majors);
|
|
|
|
mtd_for_each_device(mtd)
|
|
- if (mtd->type != MTD_ABSENT)
|
|
+ if (mtd->type != MTD_ABSENT && mtd->type != MTD_UBIVOLUME)
|
|
tr->add_mtd(tr, mtd);
|
|
|
|
mutex_unlock(&mtd_table_mutex);
|
|
diff --git drivers/mtd/nand/fsl_ifc_nand.c drivers/mtd/nand/fsl_ifc_nand.c
|
|
index 0d4928161439..be7d9eb7359c 100644
|
|
--- drivers/mtd/nand/fsl_ifc_nand.c
|
|
+++ drivers/mtd/nand/fsl_ifc_nand.c
|
|
@@ -33,7 +33,7 @@
|
|
|
|
#define ERR_BYTE 0xFF /* Value returned for read
|
|
bytes when read failed */
|
|
-#define IFC_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait
|
|
+#define IFC_TIMEOUT_MSECS 1000 /* Maximum timeout to wait
|
|
for IFC NAND Machine */
|
|
|
|
struct fsl_ifc_ctrl;
|
|
diff --git drivers/net/bonding/bond_alb.c drivers/net/bonding/bond_alb.c
|
|
index 4926c3e06e4e..6cd4e024b41d 100644
|
|
--- drivers/net/bonding/bond_alb.c
|
|
+++ drivers/net/bonding/bond_alb.c
|
|
@@ -988,7 +988,8 @@ static int alb_upper_dev_walk(struct net_device *upper, void *_data)
|
|
if (netif_is_macvlan(upper) && !strict_match) {
|
|
tags = bond_verify_device_path(bond->dev, upper, 0);
|
|
if (IS_ERR_OR_NULL(tags))
|
|
- BUG();
|
|
+ return -ENOMEM;
|
|
+
|
|
alb_send_lp_vid(slave, upper->dev_addr,
|
|
tags[0].vlan_proto, tags[0].vlan_id);
|
|
kfree(tags);
|
|
diff --git drivers/net/ethernet/aquantia/atlantic/aq_nic.c drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
index 7a900f76c9ac..396c335909af 100644
|
|
--- drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
+++ drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
@@ -884,7 +884,6 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self,
|
|
default:
|
|
err = -1;
|
|
goto err_exit;
|
|
- break;
|
|
}
|
|
if (!(self->aq_hw_caps.link_speed_msk & rate)) {
|
|
err = -1;
|
|
diff --git drivers/net/ethernet/broadcom/bnxt/bnxt.c drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
index ee438674d6cc..180a7ef588cf 100644
|
|
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
+++ drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
@@ -7092,6 +7092,8 @@ static void bnxt_sp_task(struct work_struct *work)
|
|
bnxt_cfg_ntp_filters(bp);
|
|
if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
|
|
bnxt_hwrm_exec_fwd_req(bp);
|
|
+ if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event))
|
|
+ netdev_info(bp->dev, "Receive PF driver unload event!\n");
|
|
if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) {
|
|
bnxt_hwrm_tunnel_dst_port_alloc(
|
|
bp, bp->vxlan_port,
|
|
@@ -7583,8 +7585,6 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp)
|
|
}
|
|
}
|
|
}
|
|
- if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event))
|
|
- netdev_info(bp->dev, "Receive PF driver unload event!");
|
|
}
|
|
|
|
#else
|
|
diff --git drivers/net/ethernet/broadcom/tg3.c drivers/net/ethernet/broadcom/tg3.c
|
|
index dc27c81ad512..44556eea780b 100644
|
|
--- drivers/net/ethernet/broadcom/tg3.c
|
|
+++ drivers/net/ethernet/broadcom/tg3.c
|
|
@@ -6434,6 +6434,14 @@ static void tg3_dump_state(struct tg3 *tp)
|
|
int i;
|
|
u32 *regs;
|
|
|
|
+ /* If it is a PCI error, all registers will be 0xffff,
|
|
+ * we don't dump them out, just report the error and return
|
|
+ */
|
|
+ if (tp->pdev->error_state != pci_channel_io_normal) {
|
|
+ netdev_err(tp->dev, "PCI channel ERROR!\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
regs = kzalloc(TG3_REG_BLK_SIZE, GFP_ATOMIC);
|
|
if (!regs)
|
|
return;
|
|
@@ -11168,7 +11176,8 @@ static void tg3_reset_task(struct work_struct *work)
|
|
rtnl_lock();
|
|
tg3_full_lock(tp, 0);
|
|
|
|
- if (tp->pcierr_recovery || !netif_running(tp->dev)) {
|
|
+ if (tp->pcierr_recovery || !netif_running(tp->dev) ||
|
|
+ tp->pdev->error_state != pci_channel_io_normal) {
|
|
tg3_flag_clear(tp, RESET_TASK_PENDING);
|
|
tg3_full_unlock(tp);
|
|
rtnl_unlock();
|
|
diff --git drivers/net/ethernet/cisco/enic/enic_ethtool.c drivers/net/ethernet/cisco/enic/enic_ethtool.c
|
|
index fd3980cc1e34..3280fbad5d5a 100644
|
|
--- drivers/net/ethernet/cisco/enic/enic_ethtool.c
|
|
+++ drivers/net/ethernet/cisco/enic/enic_ethtool.c
|
|
@@ -378,7 +378,6 @@ static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
- break;
|
|
}
|
|
|
|
fsp->h_u.tcp_ip4_spec.ip4src = flow_get_u32_src(&n->keys);
|
|
diff --git drivers/net/ethernet/freescale/fec_main.c drivers/net/ethernet/freescale/fec_main.c
|
|
index 1085f1d721b0..4b169890d301 100644
|
|
--- drivers/net/ethernet/freescale/fec_main.c
|
|
+++ drivers/net/ethernet/freescale/fec_main.c
|
|
@@ -1746,6 +1746,7 @@ static void fec_enet_adjust_link(struct net_device *ndev)
|
|
|
|
/* if any of the above changed restart the FEC */
|
|
if (status_change) {
|
|
+ netif_stop_queue(ndev);
|
|
napi_disable(&fep->napi);
|
|
netif_tx_lock_bh(ndev);
|
|
fec_restart(ndev);
|
|
@@ -1755,6 +1756,7 @@ static void fec_enet_adjust_link(struct net_device *ndev)
|
|
}
|
|
} else {
|
|
if (fep->link) {
|
|
+ netif_stop_queue(ndev);
|
|
napi_disable(&fep->napi);
|
|
netif_tx_lock_bh(ndev);
|
|
fec_stop(ndev);
|
|
diff --git drivers/net/ethernet/intel/i40e/i40e_main.c drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
index a783ebb14db9..ec5da7cbf416 100644
|
|
--- drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
+++ drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
@@ -4708,7 +4708,7 @@ static int i40e_pf_wait_queues_disabled(struct i40e_pf *pf)
|
|
{
|
|
int v, ret = 0;
|
|
|
|
- for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
|
|
+ for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
if (pf->vsi[v]) {
|
|
ret = i40e_vsi_wait_queues_disabled(pf->vsi[v]);
|
|
if (ret)
|
|
diff --git drivers/net/ethernet/intel/ixgbe/ixgbe_common.c drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
|
|
index 6b5662674c75..71583f8756c2 100644
|
|
--- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
|
|
+++ drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
|
|
@@ -55,7 +55,7 @@ static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
|
|
u16 words, u16 *data);
|
|
static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
|
|
u16 offset);
|
|
-static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
|
|
+static s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw);
|
|
|
|
/* Base table for registers values that change by MAC */
|
|
const u32 ixgbe_mvals_8259X[IXGBE_MVALS_IDX_LIMIT] = {
|
|
@@ -771,10 +771,10 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
|
|
usleep_range(1000, 2000);
|
|
|
|
/*
|
|
- * Prevent the PCI-E bus from from hanging by disabling PCI-E master
|
|
+ * Prevent the PCI-E bus from hanging by disabling PCI-E primary
|
|
* access and verify no pending requests
|
|
*/
|
|
- return ixgbe_disable_pcie_master(hw);
|
|
+ return ixgbe_disable_pcie_primary(hw);
|
|
}
|
|
|
|
/**
|
|
@@ -2530,15 +2530,15 @@ static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw)
|
|
}
|
|
|
|
/**
|
|
- * ixgbe_disable_pcie_master - Disable PCI-express master access
|
|
+ * ixgbe_disable_pcie_primary - Disable PCI-express primary access
|
|
* @hw: pointer to hardware structure
|
|
*
|
|
- * Disables PCI-Express master access and verifies there are no pending
|
|
- * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
|
|
- * bit hasn't caused the master requests to be disabled, else 0
|
|
- * is returned signifying master requests disabled.
|
|
+ * Disables PCI-Express primary access and verifies there are no pending
|
|
+ * requests. IXGBE_ERR_PRIMARY_REQUESTS_PENDING is returned if primary disable
|
|
+ * bit hasn't caused the primary requests to be disabled, else 0
|
|
+ * is returned signifying primary requests disabled.
|
|
**/
|
|
-static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
|
|
+static s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw)
|
|
{
|
|
u32 i, poll;
|
|
u16 value;
|
|
@@ -2547,23 +2547,23 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
|
|
IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
|
|
|
|
/* Poll for bit to read as set */
|
|
- for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
|
|
+ for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) {
|
|
if (IXGBE_READ_REG(hw, IXGBE_CTRL) & IXGBE_CTRL_GIO_DIS)
|
|
break;
|
|
usleep_range(100, 120);
|
|
}
|
|
- if (i >= IXGBE_PCI_MASTER_DISABLE_TIMEOUT) {
|
|
+ if (i >= IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT) {
|
|
hw_dbg(hw, "GIO disable did not set - requesting resets\n");
|
|
goto gio_disable_fail;
|
|
}
|
|
|
|
- /* Exit if master requests are blocked */
|
|
+ /* Exit if primary requests are blocked */
|
|
if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
|
|
ixgbe_removed(hw->hw_addr))
|
|
return 0;
|
|
|
|
- /* Poll for master request bit to clear */
|
|
- for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
|
|
+ /* Poll for primary request bit to clear */
|
|
+ for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) {
|
|
udelay(100);
|
|
if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
|
|
return 0;
|
|
@@ -2571,13 +2571,13 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
|
|
|
|
/*
|
|
* Two consecutive resets are required via CTRL.RST per datasheet
|
|
- * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine
|
|
- * of this need. The first reset prevents new master requests from
|
|
+ * 5.2.5.3.2 Primary Disable. We set a flag to inform the reset routine
|
|
+ * of this need. The first reset prevents new primary requests from
|
|
* being issued by our device. We then must wait 1usec or more for any
|
|
* remaining completions from the PCIe bus to trickle in, and then reset
|
|
* again to clear out any effects they may have had on our device.
|
|
*/
|
|
- hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n");
|
|
+ hw_dbg(hw, "GIO Primary Disable bit didn't clear - requesting resets\n");
|
|
gio_disable_fail:
|
|
hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
|
|
|
|
@@ -2599,7 +2599,7 @@ gio_disable_fail:
|
|
}
|
|
|
|
hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
|
|
- return IXGBE_ERR_MASTER_REQUESTS_PENDING;
|
|
+ return IXGBE_ERR_PRIMARY_REQUESTS_PENDING;
|
|
}
|
|
|
|
/**
|
|
diff --git drivers/net/ethernet/intel/ixgbe/ixgbe_main.c drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
|
index ac9835e61602..ca9bdaed31c5 100644
|
|
--- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
|
+++ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
|
@@ -2660,7 +2660,6 @@ static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter)
|
|
{
|
|
struct ixgbe_hw *hw = &adapter->hw;
|
|
u32 eicr = adapter->interrupt_event;
|
|
- s32 rc;
|
|
|
|
if (test_bit(__IXGBE_DOWN, &adapter->state))
|
|
return;
|
|
@@ -2694,14 +2693,13 @@ static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter)
|
|
}
|
|
|
|
/* Check if this is not due to overtemp */
|
|
- if (hw->phy.ops.check_overtemp(hw) != IXGBE_ERR_OVERTEMP)
|
|
+ if (!hw->phy.ops.check_overtemp(hw))
|
|
return;
|
|
|
|
break;
|
|
case IXGBE_DEV_ID_X550EM_A_1G_T:
|
|
case IXGBE_DEV_ID_X550EM_A_1G_T_L:
|
|
- rc = hw->phy.ops.check_overtemp(hw);
|
|
- if (rc != IXGBE_ERR_OVERTEMP)
|
|
+ if (!hw->phy.ops.check_overtemp(hw))
|
|
return;
|
|
break;
|
|
default:
|
|
@@ -5690,8 +5688,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
|
|
case IXGBE_ERR_SFP_NOT_PRESENT:
|
|
case IXGBE_ERR_SFP_NOT_SUPPORTED:
|
|
break;
|
|
- case IXGBE_ERR_MASTER_REQUESTS_PENDING:
|
|
- e_dev_err("master disable timed out\n");
|
|
+ case IXGBE_ERR_PRIMARY_REQUESTS_PENDING:
|
|
+ e_dev_err("primary disable timed out\n");
|
|
break;
|
|
case IXGBE_ERR_EEPROM_VERSION:
|
|
/* We are running on a pre-production device, log a warning */
|
|
@@ -7636,7 +7634,7 @@ static void ixgbe_service_timer(unsigned long data)
|
|
static void ixgbe_phy_interrupt_subtask(struct ixgbe_adapter *adapter)
|
|
{
|
|
struct ixgbe_hw *hw = &adapter->hw;
|
|
- u32 status;
|
|
+ bool overtemp;
|
|
|
|
if (!(adapter->flags2 & IXGBE_FLAG2_PHY_INTERRUPT))
|
|
return;
|
|
@@ -7646,11 +7644,9 @@ static void ixgbe_phy_interrupt_subtask(struct ixgbe_adapter *adapter)
|
|
if (!hw->phy.ops.handle_lasi)
|
|
return;
|
|
|
|
- status = hw->phy.ops.handle_lasi(&adapter->hw);
|
|
- if (status != IXGBE_ERR_OVERTEMP)
|
|
- return;
|
|
-
|
|
- e_crit(drv, "%s\n", ixgbe_overheat_msg);
|
|
+ hw->phy.ops.handle_lasi(&adapter->hw, &overtemp);
|
|
+ if (overtemp)
|
|
+ e_crit(drv, "%s\n", ixgbe_overheat_msg);
|
|
}
|
|
|
|
static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
|
|
diff --git drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
|
|
index 654a402f0e9e..09a7c0f4aa2a 100644
|
|
--- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
|
|
+++ drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
|
|
@@ -429,8 +429,7 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
|
|
return status;
|
|
|
|
/* Don't reset PHY if it's shut down due to overtemp. */
|
|
- if (!hw->phy.reset_if_overtemp &&
|
|
- (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
|
|
+ if (!hw->phy.reset_if_overtemp && hw->phy.ops.check_overtemp(hw))
|
|
return 0;
|
|
|
|
/* Blocked by MNG FW so bail */
|
|
@@ -2329,22 +2328,24 @@ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
|
|
* @hw: pointer to hardware structure
|
|
*
|
|
* Checks if the LASI temp alarm status was triggered due to overtemp
|
|
+ *
|
|
+ * Return true when an overtemp event detected, otherwise false.
|
|
**/
|
|
-s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
|
|
+bool ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
|
|
{
|
|
u16 phy_data = 0;
|
|
+ u32 status;
|
|
|
|
if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM)
|
|
- return 0;
|
|
+ return false;
|
|
|
|
/* Check that the LASI temp alarm status was triggered */
|
|
- hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
|
|
- MDIO_MMD_PMAPMD, &phy_data);
|
|
-
|
|
- if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM))
|
|
- return 0;
|
|
+ status = hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
|
|
+ MDIO_MMD_PMAPMD, &phy_data);
|
|
+ if (status)
|
|
+ return false;
|
|
|
|
- return IXGBE_ERR_OVERTEMP;
|
|
+ return !!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM);
|
|
}
|
|
|
|
/** ixgbe_set_copper_phy_power - Control power for copper phy
|
|
diff --git drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
|
|
index 94df1d99be95..7002f0a534c7 100644
|
|
--- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
|
|
+++ drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
|
|
@@ -178,7 +178,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
|
|
s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
|
|
u16 *list_offset,
|
|
u16 *data_offset);
|
|
-s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
|
|
+bool ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
|
|
s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
|
|
u8 dev_addr, u8 *data);
|
|
s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
|
|
diff --git drivers/net/ethernet/intel/ixgbe/ixgbe_type.h drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
|
|
index ffa0ee5cd0f5..93d18050284d 100644
|
|
--- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
|
|
+++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
|
|
@@ -1227,7 +1227,7 @@ struct ixgbe_thermal_sensor_data {
|
|
#define IXGBE_PSRTYPE_RQPL_SHIFT 29
|
|
|
|
/* CTRL Bit Masks */
|
|
-#define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */
|
|
+#define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Primary Disable bit */
|
|
#define IXGBE_CTRL_LNK_RST 0x00000008 /* Link Reset. Resets everything. */
|
|
#define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */
|
|
#define IXGBE_CTRL_RST_MASK (IXGBE_CTRL_LNK_RST | IXGBE_CTRL_RST)
|
|
@@ -1790,7 +1790,7 @@ enum {
|
|
/* STATUS Bit Masks */
|
|
#define IXGBE_STATUS_LAN_ID 0x0000000C /* LAN ID */
|
|
#define IXGBE_STATUS_LAN_ID_SHIFT 2 /* LAN ID Shift*/
|
|
-#define IXGBE_STATUS_GIO 0x00080000 /* GIO Master Enable Status */
|
|
+#define IXGBE_STATUS_GIO 0x00080000 /* GIO Primary Enable Status */
|
|
|
|
#define IXGBE_STATUS_LAN_ID_0 0x00000000 /* LAN ID 0 */
|
|
#define IXGBE_STATUS_LAN_ID_1 0x00000004 /* LAN ID 1 */
|
|
@@ -2172,8 +2172,8 @@ enum {
|
|
#define IXGBE_PCIDEVCTRL2_4_8s 0xd
|
|
#define IXGBE_PCIDEVCTRL2_17_34s 0xe
|
|
|
|
-/* Number of 100 microseconds we wait for PCI Express master disable */
|
|
-#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
|
|
+/* Number of 100 microseconds we wait for PCI Express primary disable */
|
|
+#define IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT 800
|
|
|
|
/* RAH */
|
|
#define IXGBE_RAH_VIND_MASK 0x003C0000
|
|
@@ -3482,10 +3482,10 @@ struct ixgbe_phy_operations {
|
|
s32 (*read_i2c_sff8472)(struct ixgbe_hw *, u8 , u8 *);
|
|
s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
|
|
s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8);
|
|
- s32 (*check_overtemp)(struct ixgbe_hw *);
|
|
+ bool (*check_overtemp)(struct ixgbe_hw *);
|
|
s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
|
|
s32 (*enter_lplu)(struct ixgbe_hw *);
|
|
- s32 (*handle_lasi)(struct ixgbe_hw *hw);
|
|
+ s32 (*handle_lasi)(struct ixgbe_hw *hw, bool *);
|
|
s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
|
|
u8 *value);
|
|
s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
|
|
@@ -3651,7 +3651,7 @@ struct ixgbe_info {
|
|
#define IXGBE_ERR_ADAPTER_STOPPED -9
|
|
#define IXGBE_ERR_INVALID_MAC_ADDR -10
|
|
#define IXGBE_ERR_DEVICE_NOT_SUPPORTED -11
|
|
-#define IXGBE_ERR_MASTER_REQUESTS_PENDING -12
|
|
+#define IXGBE_ERR_PRIMARY_REQUESTS_PENDING -12
|
|
#define IXGBE_ERR_INVALID_LINK_SETTINGS -13
|
|
#define IXGBE_ERR_AUTONEG_NOT_COMPLETE -14
|
|
#define IXGBE_ERR_RESET_FAILED -15
|
|
diff --git drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
|
|
index 6ea0d6a5fb90..b5e4e78f86ee 100644
|
|
--- drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
|
|
+++ drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
|
|
@@ -375,7 +375,6 @@ static s32 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
|
|
if (ixgbe_read_eerd_generic(hw, pointer, &length)) {
|
|
hw_dbg(hw, "EEPROM read failed\n");
|
|
return IXGBE_ERR_EEPROM;
|
|
- break;
|
|
}
|
|
|
|
/* Skip pointer section if length is invalid. */
|
|
diff --git drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
|
|
index 10fa0e095ec3..f99596cf3d7e 100644
|
|
--- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
|
|
+++ drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
|
|
@@ -620,8 +620,10 @@ static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
|
|
rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
|
|
if (rc)
|
|
return rc;
|
|
+
|
|
if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
|
|
- return IXGBE_ERR_OVERTEMP;
|
|
+ return -EIO;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -735,7 +737,8 @@ static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
|
|
error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
|
|
IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
|
|
hw_dbg(hw, "Failed to read, error %x\n", error);
|
|
- return IXGBE_ERR_PHY;
|
|
+ ret = IXGBE_ERR_PHY;
|
|
+ goto out;
|
|
}
|
|
|
|
if (!ret)
|
|
@@ -2314,18 +2317,18 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
|
|
* @hw: pointer to hardware structure
|
|
* @lsc: pointer to boolean flag which indicates whether external Base T
|
|
* PHY interrupt is lsc
|
|
+ * @is_overtemp: indicate whether an overtemp event encountered
|
|
*
|
|
* Determime if external Base T PHY interrupt cause is high temperature
|
|
* failure alarm or link status change.
|
|
- *
|
|
- * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
|
|
- * failure alarm, else return PHY access status.
|
|
**/
|
|
-static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
|
|
+static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc,
|
|
+ bool *is_overtemp)
|
|
{
|
|
u32 status;
|
|
u16 reg;
|
|
|
|
+ *is_overtemp = false;
|
|
*lsc = false;
|
|
|
|
/* Vendor alarm triggered */
|
|
@@ -2357,7 +2360,8 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
|
|
if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
|
|
/* power down the PHY in case the PHY FW didn't already */
|
|
ixgbe_set_copper_phy_power(hw, false);
|
|
- return IXGBE_ERR_OVERTEMP;
|
|
+ *is_overtemp = true;
|
|
+ return -EIO;
|
|
}
|
|
if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
|
|
/* device fault alarm triggered */
|
|
@@ -2371,7 +2375,8 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
|
|
if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
|
|
/* power down the PHY in case the PHY FW didn't */
|
|
ixgbe_set_copper_phy_power(hw, false);
|
|
- return IXGBE_ERR_OVERTEMP;
|
|
+ *is_overtemp = true;
|
|
+ return -EIO;
|
|
}
|
|
}
|
|
|
|
@@ -2407,12 +2412,12 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
|
|
**/
|
|
static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
|
|
{
|
|
+ bool lsc, overtemp;
|
|
u32 status;
|
|
u16 reg;
|
|
- bool lsc;
|
|
|
|
/* Clear interrupt flags */
|
|
- status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
|
|
+ status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, &overtemp);
|
|
|
|
/* Enable link status change alarm */
|
|
|
|
@@ -2491,21 +2496,20 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
|
|
/**
|
|
* ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
|
|
* @hw: pointer to hardware structure
|
|
+ * @is_overtemp: indicate whether an overtemp event encountered
|
|
*
|
|
* Handle external Base T PHY interrupt. If high temperature
|
|
* failure alarm then return error, else if link status change
|
|
* then setup internal/external PHY link
|
|
- *
|
|
- * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
|
|
- * failure alarm, else return PHY access status.
|
|
**/
|
|
-static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
|
|
+static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw,
|
|
+ bool *is_overtemp)
|
|
{
|
|
struct ixgbe_phy_info *phy = &hw->phy;
|
|
bool lsc;
|
|
u32 status;
|
|
|
|
- status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
|
|
+ status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, is_overtemp);
|
|
if (status)
|
|
return status;
|
|
|
|
@@ -3132,21 +3136,23 @@ static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
|
|
/**
|
|
* ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
|
|
* @hw: pointer to hardware structure
|
|
+ *
|
|
+ * Return true when an overtemp event detected, otherwise false.
|
|
*/
|
|
-static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
|
|
+static bool ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
|
|
{
|
|
u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
|
|
s32 rc;
|
|
|
|
rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
|
|
if (rc)
|
|
- return rc;
|
|
+ return false;
|
|
|
|
if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
|
|
ixgbe_shutdown_fw_phy(hw);
|
|
- return IXGBE_ERR_OVERTEMP;
|
|
+ return true;
|
|
}
|
|
- return 0;
|
|
+ return false;
|
|
}
|
|
|
|
/**
|
|
diff --git drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
|
|
index c567cff499d1..b8c7997ea52b 100644
|
|
--- drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
|
|
+++ drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
|
|
@@ -229,11 +229,13 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
|
|
|
|
ft->g = kcalloc(MLX5E_ARFS_NUM_GROUPS,
|
|
sizeof(*ft->g), GFP_KERNEL);
|
|
- in = kvzalloc(inlen, GFP_KERNEL);
|
|
- if (!in || !ft->g) {
|
|
- kvfree(ft->g);
|
|
- kvfree(in);
|
|
+ if (!ft->g)
|
|
return -ENOMEM;
|
|
+
|
|
+ in = kvzalloc(inlen, GFP_KERNEL);
|
|
+ if (!in) {
|
|
+ err = -ENOMEM;
|
|
+ goto err_free_g;
|
|
}
|
|
|
|
mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
|
|
@@ -253,7 +255,7 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
|
|
break;
|
|
default:
|
|
err = -EINVAL;
|
|
- goto out;
|
|
+ goto err_free_in;
|
|
}
|
|
|
|
switch (type) {
|
|
@@ -275,7 +277,7 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
|
|
break;
|
|
default:
|
|
err = -EINVAL;
|
|
- goto out;
|
|
+ goto err_free_in;
|
|
}
|
|
|
|
MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
|
|
@@ -284,7 +286,7 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
|
|
MLX5_SET_CFG(in, end_flow_index, ix - 1);
|
|
ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
|
|
if (IS_ERR(ft->g[ft->num_groups]))
|
|
- goto err;
|
|
+ goto err_clean_group;
|
|
ft->num_groups++;
|
|
|
|
memset(in, 0, inlen);
|
|
@@ -293,18 +295,20 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
|
|
MLX5_SET_CFG(in, end_flow_index, ix - 1);
|
|
ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
|
|
if (IS_ERR(ft->g[ft->num_groups]))
|
|
- goto err;
|
|
+ goto err_clean_group;
|
|
ft->num_groups++;
|
|
|
|
kvfree(in);
|
|
return 0;
|
|
|
|
-err:
|
|
+err_clean_group:
|
|
err = PTR_ERR(ft->g[ft->num_groups]);
|
|
ft->g[ft->num_groups] = NULL;
|
|
-out:
|
|
+err_free_in:
|
|
kvfree(in);
|
|
-
|
|
+err_free_g:
|
|
+ kfree(ft->g);
|
|
+ ft->g = NULL;
|
|
return err;
|
|
}
|
|
|
|
diff --git drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
|
|
index cd678323bacb..375c1c4ffc0c 100644
|
|
--- drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
|
|
+++ drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
|
|
@@ -571,11 +571,13 @@ static int enable_bars(struct nfp6000_pcie *nfp, u16 interface)
|
|
const u32 barcfg_msix_general =
|
|
NFP_PCIE_BAR_PCIE2CPP_MapType(
|
|
NFP_PCIE_BAR_PCIE2CPP_MapType_GENERAL) |
|
|
- NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT;
|
|
+ NFP_PCIE_BAR_PCIE2CPP_LengthSelect(
|
|
+ NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT);
|
|
const u32 barcfg_msix_xpb =
|
|
NFP_PCIE_BAR_PCIE2CPP_MapType(
|
|
NFP_PCIE_BAR_PCIE2CPP_MapType_BULK) |
|
|
- NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT |
|
|
+ NFP_PCIE_BAR_PCIE2CPP_LengthSelect(
|
|
+ NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT) |
|
|
NFP_PCIE_BAR_PCIE2CPP_Target_BaseAddress(
|
|
NFP_CPP_TARGET_ISLAND_XPB);
|
|
const u32 barcfg_explicit[4] = {
|
|
diff --git drivers/net/ethernet/qlogic/qla3xxx.c drivers/net/ethernet/qlogic/qla3xxx.c
|
|
index 6c8a591db713..bc3d268916b8 100644
|
|
--- drivers/net/ethernet/qlogic/qla3xxx.c
|
|
+++ drivers/net/ethernet/qlogic/qla3xxx.c
|
|
@@ -316,12 +316,11 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
|
|
* buffer
|
|
*/
|
|
skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
|
|
- map = pci_map_single(qdev->pdev,
|
|
+ map = dma_map_single(&qdev->pdev->dev,
|
|
lrg_buf_cb->skb->data,
|
|
- qdev->lrg_buffer_len -
|
|
- QL_HEADER_SPACE,
|
|
- PCI_DMA_FROMDEVICE);
|
|
- err = pci_dma_mapping_error(qdev->pdev, map);
|
|
+ qdev->lrg_buffer_len - QL_HEADER_SPACE,
|
|
+ DMA_FROM_DEVICE);
|
|
+ err = dma_mapping_error(&qdev->pdev->dev, map);
|
|
if (err) {
|
|
netdev_err(qdev->ndev,
|
|
"PCI mapping failed with error: %d\n",
|
|
@@ -1803,13 +1802,12 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
|
|
* first buffer
|
|
*/
|
|
skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
|
|
- map = pci_map_single(qdev->pdev,
|
|
+ map = dma_map_single(&qdev->pdev->dev,
|
|
lrg_buf_cb->skb->data,
|
|
- qdev->lrg_buffer_len -
|
|
- QL_HEADER_SPACE,
|
|
- PCI_DMA_FROMDEVICE);
|
|
+ qdev->lrg_buffer_len - QL_HEADER_SPACE,
|
|
+ DMA_FROM_DEVICE);
|
|
|
|
- err = pci_dma_mapping_error(qdev->pdev, map);
|
|
+ err = dma_mapping_error(&qdev->pdev->dev, map);
|
|
if (err) {
|
|
netdev_err(qdev->ndev,
|
|
"PCI mapping failed with error: %d\n",
|
|
@@ -1944,18 +1942,16 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
|
|
goto invalid_seg_count;
|
|
}
|
|
|
|
- pci_unmap_single(qdev->pdev,
|
|
+ dma_unmap_single(&qdev->pdev->dev,
|
|
dma_unmap_addr(&tx_cb->map[0], mapaddr),
|
|
- dma_unmap_len(&tx_cb->map[0], maplen),
|
|
- PCI_DMA_TODEVICE);
|
|
+ dma_unmap_len(&tx_cb->map[0], maplen), DMA_TO_DEVICE);
|
|
tx_cb->seg_count--;
|
|
if (tx_cb->seg_count) {
|
|
for (i = 1; i < tx_cb->seg_count; i++) {
|
|
- pci_unmap_page(qdev->pdev,
|
|
- dma_unmap_addr(&tx_cb->map[i],
|
|
- mapaddr),
|
|
+ dma_unmap_page(&qdev->pdev->dev,
|
|
+ dma_unmap_addr(&tx_cb->map[i], mapaddr),
|
|
dma_unmap_len(&tx_cb->map[i], maplen),
|
|
- PCI_DMA_TODEVICE);
|
|
+ DMA_TO_DEVICE);
|
|
}
|
|
}
|
|
qdev->ndev->stats.tx_packets++;
|
|
@@ -2022,10 +2018,9 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
|
|
qdev->ndev->stats.rx_bytes += length;
|
|
|
|
skb_put(skb, length);
|
|
- pci_unmap_single(qdev->pdev,
|
|
+ dma_unmap_single(&qdev->pdev->dev,
|
|
dma_unmap_addr(lrg_buf_cb2, mapaddr),
|
|
- dma_unmap_len(lrg_buf_cb2, maplen),
|
|
- PCI_DMA_FROMDEVICE);
|
|
+ dma_unmap_len(lrg_buf_cb2, maplen), DMA_FROM_DEVICE);
|
|
prefetch(skb->data);
|
|
skb_checksum_none_assert(skb);
|
|
skb->protocol = eth_type_trans(skb, qdev->ndev);
|
|
@@ -2068,10 +2063,9 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
|
|
skb2 = lrg_buf_cb2->skb;
|
|
|
|
skb_put(skb2, length); /* Just the second buffer length here. */
|
|
- pci_unmap_single(qdev->pdev,
|
|
+ dma_unmap_single(&qdev->pdev->dev,
|
|
dma_unmap_addr(lrg_buf_cb2, mapaddr),
|
|
- dma_unmap_len(lrg_buf_cb2, maplen),
|
|
- PCI_DMA_FROMDEVICE);
|
|
+ dma_unmap_len(lrg_buf_cb2, maplen), DMA_FROM_DEVICE);
|
|
prefetch(skb2->data);
|
|
|
|
skb_checksum_none_assert(skb2);
|
|
@@ -2320,9 +2314,9 @@ static int ql_send_map(struct ql3_adapter *qdev,
|
|
/*
|
|
* Map the skb buffer first.
|
|
*/
|
|
- map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
|
|
+ map = dma_map_single(&qdev->pdev->dev, skb->data, len, DMA_TO_DEVICE);
|
|
|
|
- err = pci_dma_mapping_error(qdev->pdev, map);
|
|
+ err = dma_mapping_error(&qdev->pdev->dev, map);
|
|
if (err) {
|
|
netdev_err(qdev->ndev, "PCI mapping failed with error: %d\n",
|
|
err);
|
|
@@ -2358,11 +2352,11 @@ static int ql_send_map(struct ql3_adapter *qdev,
|
|
(seg == 7 && seg_cnt > 8) ||
|
|
(seg == 12 && seg_cnt > 13) ||
|
|
(seg == 17 && seg_cnt > 18)) {
|
|
- map = pci_map_single(qdev->pdev, oal,
|
|
+ map = dma_map_single(&qdev->pdev->dev, oal,
|
|
sizeof(struct oal),
|
|
- PCI_DMA_TODEVICE);
|
|
+ DMA_TO_DEVICE);
|
|
|
|
- err = pci_dma_mapping_error(qdev->pdev, map);
|
|
+ err = dma_mapping_error(&qdev->pdev->dev, map);
|
|
if (err) {
|
|
netdev_err(qdev->ndev,
|
|
"PCI mapping outbound address list with error: %d\n",
|
|
@@ -2424,24 +2418,24 @@ map_error:
|
|
(seg == 7 && seg_cnt > 8) ||
|
|
(seg == 12 && seg_cnt > 13) ||
|
|
(seg == 17 && seg_cnt > 18)) {
|
|
- pci_unmap_single(qdev->pdev,
|
|
- dma_unmap_addr(&tx_cb->map[seg], mapaddr),
|
|
- dma_unmap_len(&tx_cb->map[seg], maplen),
|
|
- PCI_DMA_TODEVICE);
|
|
+ dma_unmap_single(&qdev->pdev->dev,
|
|
+ dma_unmap_addr(&tx_cb->map[seg], mapaddr),
|
|
+ dma_unmap_len(&tx_cb->map[seg], maplen),
|
|
+ DMA_TO_DEVICE);
|
|
oal++;
|
|
seg++;
|
|
}
|
|
|
|
- pci_unmap_page(qdev->pdev,
|
|
+ dma_unmap_page(&qdev->pdev->dev,
|
|
dma_unmap_addr(&tx_cb->map[seg], mapaddr),
|
|
dma_unmap_len(&tx_cb->map[seg], maplen),
|
|
- PCI_DMA_TODEVICE);
|
|
+ DMA_TO_DEVICE);
|
|
}
|
|
|
|
- pci_unmap_single(qdev->pdev,
|
|
+ dma_unmap_single(&qdev->pdev->dev,
|
|
dma_unmap_addr(&tx_cb->map[0], mapaddr),
|
|
dma_unmap_addr(&tx_cb->map[0], maplen),
|
|
- PCI_DMA_TODEVICE);
|
|
+ DMA_TO_DEVICE);
|
|
|
|
return NETDEV_TX_BUSY;
|
|
|
|
@@ -2527,9 +2521,8 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
|
|
wmb();
|
|
|
|
qdev->req_q_virt_addr =
|
|
- pci_alloc_consistent(qdev->pdev,
|
|
- (size_t) qdev->req_q_size,
|
|
- &qdev->req_q_phy_addr);
|
|
+ dma_alloc_coherent(&qdev->pdev->dev, (size_t)qdev->req_q_size,
|
|
+ &qdev->req_q_phy_addr, GFP_KERNEL);
|
|
|
|
if ((qdev->req_q_virt_addr == NULL) ||
|
|
LS_64BITS(qdev->req_q_phy_addr) & (qdev->req_q_size - 1)) {
|
|
@@ -2538,16 +2531,14 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
|
|
}
|
|
|
|
qdev->rsp_q_virt_addr =
|
|
- pci_alloc_consistent(qdev->pdev,
|
|
- (size_t) qdev->rsp_q_size,
|
|
- &qdev->rsp_q_phy_addr);
|
|
+ dma_alloc_coherent(&qdev->pdev->dev, (size_t)qdev->rsp_q_size,
|
|
+ &qdev->rsp_q_phy_addr, GFP_KERNEL);
|
|
|
|
if ((qdev->rsp_q_virt_addr == NULL) ||
|
|
LS_64BITS(qdev->rsp_q_phy_addr) & (qdev->rsp_q_size - 1)) {
|
|
netdev_err(qdev->ndev, "rspQ allocation failed\n");
|
|
- pci_free_consistent(qdev->pdev, (size_t) qdev->req_q_size,
|
|
- qdev->req_q_virt_addr,
|
|
- qdev->req_q_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev, (size_t)qdev->req_q_size,
|
|
+ qdev->req_q_virt_addr, qdev->req_q_phy_addr);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -2563,15 +2554,13 @@ static void ql_free_net_req_rsp_queues(struct ql3_adapter *qdev)
|
|
return;
|
|
}
|
|
|
|
- pci_free_consistent(qdev->pdev,
|
|
- qdev->req_q_size,
|
|
- qdev->req_q_virt_addr, qdev->req_q_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev, qdev->req_q_size,
|
|
+ qdev->req_q_virt_addr, qdev->req_q_phy_addr);
|
|
|
|
qdev->req_q_virt_addr = NULL;
|
|
|
|
- pci_free_consistent(qdev->pdev,
|
|
- qdev->rsp_q_size,
|
|
- qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev, qdev->rsp_q_size,
|
|
+ qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr);
|
|
|
|
qdev->rsp_q_virt_addr = NULL;
|
|
|
|
@@ -2595,12 +2584,13 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
|
|
return -ENOMEM;
|
|
|
|
qdev->lrg_buf_q_alloc_virt_addr =
|
|
- pci_alloc_consistent(qdev->pdev,
|
|
- qdev->lrg_buf_q_alloc_size,
|
|
- &qdev->lrg_buf_q_alloc_phy_addr);
|
|
+ dma_alloc_coherent(&qdev->pdev->dev,
|
|
+ qdev->lrg_buf_q_alloc_size,
|
|
+ &qdev->lrg_buf_q_alloc_phy_addr, GFP_KERNEL);
|
|
|
|
if (qdev->lrg_buf_q_alloc_virt_addr == NULL) {
|
|
netdev_err(qdev->ndev, "lBufQ failed\n");
|
|
+ kfree(qdev->lrg_buf);
|
|
return -ENOMEM;
|
|
}
|
|
qdev->lrg_buf_q_virt_addr = qdev->lrg_buf_q_alloc_virt_addr;
|
|
@@ -2615,15 +2605,17 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
|
|
qdev->small_buf_q_alloc_size = qdev->small_buf_q_size * 2;
|
|
|
|
qdev->small_buf_q_alloc_virt_addr =
|
|
- pci_alloc_consistent(qdev->pdev,
|
|
- qdev->small_buf_q_alloc_size,
|
|
- &qdev->small_buf_q_alloc_phy_addr);
|
|
+ dma_alloc_coherent(&qdev->pdev->dev,
|
|
+ qdev->small_buf_q_alloc_size,
|
|
+ &qdev->small_buf_q_alloc_phy_addr, GFP_KERNEL);
|
|
|
|
if (qdev->small_buf_q_alloc_virt_addr == NULL) {
|
|
netdev_err(qdev->ndev, "Small Buffer Queue allocation failed\n");
|
|
- pci_free_consistent(qdev->pdev, qdev->lrg_buf_q_alloc_size,
|
|
- qdev->lrg_buf_q_alloc_virt_addr,
|
|
- qdev->lrg_buf_q_alloc_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev,
|
|
+ qdev->lrg_buf_q_alloc_size,
|
|
+ qdev->lrg_buf_q_alloc_virt_addr,
|
|
+ qdev->lrg_buf_q_alloc_phy_addr);
|
|
+ kfree(qdev->lrg_buf);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -2640,17 +2632,15 @@ static void ql_free_buffer_queues(struct ql3_adapter *qdev)
|
|
return;
|
|
}
|
|
kfree(qdev->lrg_buf);
|
|
- pci_free_consistent(qdev->pdev,
|
|
- qdev->lrg_buf_q_alloc_size,
|
|
- qdev->lrg_buf_q_alloc_virt_addr,
|
|
- qdev->lrg_buf_q_alloc_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev, qdev->lrg_buf_q_alloc_size,
|
|
+ qdev->lrg_buf_q_alloc_virt_addr,
|
|
+ qdev->lrg_buf_q_alloc_phy_addr);
|
|
|
|
qdev->lrg_buf_q_virt_addr = NULL;
|
|
|
|
- pci_free_consistent(qdev->pdev,
|
|
- qdev->small_buf_q_alloc_size,
|
|
- qdev->small_buf_q_alloc_virt_addr,
|
|
- qdev->small_buf_q_alloc_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev, qdev->small_buf_q_alloc_size,
|
|
+ qdev->small_buf_q_alloc_virt_addr,
|
|
+ qdev->small_buf_q_alloc_phy_addr);
|
|
|
|
qdev->small_buf_q_virt_addr = NULL;
|
|
|
|
@@ -2668,9 +2658,9 @@ static int ql_alloc_small_buffers(struct ql3_adapter *qdev)
|
|
QL_SMALL_BUFFER_SIZE);
|
|
|
|
qdev->small_buf_virt_addr =
|
|
- pci_alloc_consistent(qdev->pdev,
|
|
- qdev->small_buf_total_size,
|
|
- &qdev->small_buf_phy_addr);
|
|
+ dma_alloc_coherent(&qdev->pdev->dev,
|
|
+ qdev->small_buf_total_size,
|
|
+ &qdev->small_buf_phy_addr, GFP_KERNEL);
|
|
|
|
if (qdev->small_buf_virt_addr == NULL) {
|
|
netdev_err(qdev->ndev, "Failed to get small buffer memory\n");
|
|
@@ -2703,10 +2693,10 @@ static void ql_free_small_buffers(struct ql3_adapter *qdev)
|
|
return;
|
|
}
|
|
if (qdev->small_buf_virt_addr != NULL) {
|
|
- pci_free_consistent(qdev->pdev,
|
|
- qdev->small_buf_total_size,
|
|
- qdev->small_buf_virt_addr,
|
|
- qdev->small_buf_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev,
|
|
+ qdev->small_buf_total_size,
|
|
+ qdev->small_buf_virt_addr,
|
|
+ qdev->small_buf_phy_addr);
|
|
|
|
qdev->small_buf_virt_addr = NULL;
|
|
}
|
|
@@ -2721,10 +2711,10 @@ static void ql_free_large_buffers(struct ql3_adapter *qdev)
|
|
lrg_buf_cb = &qdev->lrg_buf[i];
|
|
if (lrg_buf_cb->skb) {
|
|
dev_kfree_skb(lrg_buf_cb->skb);
|
|
- pci_unmap_single(qdev->pdev,
|
|
+ dma_unmap_single(&qdev->pdev->dev,
|
|
dma_unmap_addr(lrg_buf_cb, mapaddr),
|
|
dma_unmap_len(lrg_buf_cb, maplen),
|
|
- PCI_DMA_FROMDEVICE);
|
|
+ DMA_FROM_DEVICE);
|
|
memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
|
|
} else {
|
|
break;
|
|
@@ -2776,13 +2766,11 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
|
|
* buffer
|
|
*/
|
|
skb_reserve(skb, QL_HEADER_SPACE);
|
|
- map = pci_map_single(qdev->pdev,
|
|
- skb->data,
|
|
- qdev->lrg_buffer_len -
|
|
- QL_HEADER_SPACE,
|
|
- PCI_DMA_FROMDEVICE);
|
|
+ map = dma_map_single(&qdev->pdev->dev, skb->data,
|
|
+ qdev->lrg_buffer_len - QL_HEADER_SPACE,
|
|
+ DMA_FROM_DEVICE);
|
|
|
|
- err = pci_dma_mapping_error(qdev->pdev, map);
|
|
+ err = dma_mapping_error(&qdev->pdev->dev, map);
|
|
if (err) {
|
|
netdev_err(qdev->ndev,
|
|
"PCI mapping failed with error: %d\n",
|
|
@@ -2867,8 +2855,8 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
|
|
* Network Completion Queue Producer Index Register
|
|
*/
|
|
qdev->shadow_reg_virt_addr =
|
|
- pci_alloc_consistent(qdev->pdev,
|
|
- PAGE_SIZE, &qdev->shadow_reg_phy_addr);
|
|
+ dma_alloc_coherent(&qdev->pdev->dev, PAGE_SIZE,
|
|
+ &qdev->shadow_reg_phy_addr, GFP_KERNEL);
|
|
|
|
if (qdev->shadow_reg_virt_addr != NULL) {
|
|
qdev->preq_consumer_index = qdev->shadow_reg_virt_addr;
|
|
@@ -2923,10 +2911,9 @@ err_small_buffers:
|
|
err_buffer_queues:
|
|
ql_free_net_req_rsp_queues(qdev);
|
|
err_req_rsp:
|
|
- pci_free_consistent(qdev->pdev,
|
|
- PAGE_SIZE,
|
|
- qdev->shadow_reg_virt_addr,
|
|
- qdev->shadow_reg_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev, PAGE_SIZE,
|
|
+ qdev->shadow_reg_virt_addr,
|
|
+ qdev->shadow_reg_phy_addr);
|
|
|
|
return -ENOMEM;
|
|
}
|
|
@@ -2939,10 +2926,9 @@ static void ql_free_mem_resources(struct ql3_adapter *qdev)
|
|
ql_free_buffer_queues(qdev);
|
|
ql_free_net_req_rsp_queues(qdev);
|
|
if (qdev->shadow_reg_virt_addr != NULL) {
|
|
- pci_free_consistent(qdev->pdev,
|
|
- PAGE_SIZE,
|
|
- qdev->shadow_reg_virt_addr,
|
|
- qdev->shadow_reg_phy_addr);
|
|
+ dma_free_coherent(&qdev->pdev->dev, PAGE_SIZE,
|
|
+ qdev->shadow_reg_virt_addr,
|
|
+ qdev->shadow_reg_phy_addr);
|
|
qdev->shadow_reg_virt_addr = NULL;
|
|
}
|
|
}
|
|
@@ -3643,18 +3629,15 @@ static void ql_reset_work(struct work_struct *work)
|
|
if (tx_cb->skb) {
|
|
netdev_printk(KERN_DEBUG, ndev,
|
|
"Freeing lost SKB\n");
|
|
- pci_unmap_single(qdev->pdev,
|
|
- dma_unmap_addr(&tx_cb->map[0],
|
|
- mapaddr),
|
|
- dma_unmap_len(&tx_cb->map[0], maplen),
|
|
- PCI_DMA_TODEVICE);
|
|
+ dma_unmap_single(&qdev->pdev->dev,
|
|
+ dma_unmap_addr(&tx_cb->map[0], mapaddr),
|
|
+ dma_unmap_len(&tx_cb->map[0], maplen),
|
|
+ DMA_TO_DEVICE);
|
|
for (j = 1; j < tx_cb->seg_count; j++) {
|
|
- pci_unmap_page(qdev->pdev,
|
|
- dma_unmap_addr(&tx_cb->map[j],
|
|
- mapaddr),
|
|
- dma_unmap_len(&tx_cb->map[j],
|
|
- maplen),
|
|
- PCI_DMA_TODEVICE);
|
|
+ dma_unmap_page(&qdev->pdev->dev,
|
|
+ dma_unmap_addr(&tx_cb->map[j], mapaddr),
|
|
+ dma_unmap_len(&tx_cb->map[j], maplen),
|
|
+ DMA_TO_DEVICE);
|
|
}
|
|
dev_kfree_skb(tx_cb->skb);
|
|
tx_cb->skb = NULL;
|
|
@@ -3786,13 +3769,10 @@ static int ql3xxx_probe(struct pci_dev *pdev,
|
|
|
|
pci_set_master(pdev);
|
|
|
|
- if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
|
|
+ if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
|
|
pci_using_dac = 1;
|
|
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
|
|
- } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
|
|
+ else if (!(err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))))
|
|
pci_using_dac = 0;
|
|
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
|
|
- }
|
|
|
|
if (err) {
|
|
pr_err("%s no usable DMA configuration\n", pci_name(pdev));
|
|
diff --git drivers/net/ethernet/renesas/ravb_main.c drivers/net/ethernet/renesas/ravb_main.c
|
|
index b97d450214df..2190ed6b0081 100644
|
|
--- drivers/net/ethernet/renesas/ravb_main.c
|
|
+++ drivers/net/ethernet/renesas/ravb_main.c
|
|
@@ -1545,7 +1545,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|
struct ravb_tstamp_skb *ts_skb;
|
|
struct ravb_tx_desc *desc;
|
|
unsigned long flags;
|
|
- u32 dma_addr;
|
|
+ dma_addr_t dma_addr;
|
|
void *buffer;
|
|
u32 entry;
|
|
u32 len;
|
|
diff --git drivers/net/fjes/fjes_hw.c drivers/net/fjes/fjes_hw.c
|
|
index 9c652c04375b..c3fa8db69b9e 100644
|
|
--- drivers/net/fjes/fjes_hw.c
|
|
+++ drivers/net/fjes/fjes_hw.c
|
|
@@ -235,21 +235,25 @@ static int fjes_hw_setup(struct fjes_hw *hw)
|
|
|
|
mem_size = FJES_DEV_REQ_BUF_SIZE(hw->max_epid);
|
|
hw->hw_info.req_buf = kzalloc(mem_size, GFP_KERNEL);
|
|
- if (!(hw->hw_info.req_buf))
|
|
- return -ENOMEM;
|
|
+ if (!(hw->hw_info.req_buf)) {
|
|
+ result = -ENOMEM;
|
|
+ goto free_ep_info;
|
|
+ }
|
|
|
|
hw->hw_info.req_buf_size = mem_size;
|
|
|
|
mem_size = FJES_DEV_RES_BUF_SIZE(hw->max_epid);
|
|
hw->hw_info.res_buf = kzalloc(mem_size, GFP_KERNEL);
|
|
- if (!(hw->hw_info.res_buf))
|
|
- return -ENOMEM;
|
|
+ if (!(hw->hw_info.res_buf)) {
|
|
+ result = -ENOMEM;
|
|
+ goto free_req_buf;
|
|
+ }
|
|
|
|
hw->hw_info.res_buf_size = mem_size;
|
|
|
|
result = fjes_hw_alloc_shared_status_region(hw);
|
|
if (result)
|
|
- return result;
|
|
+ goto free_res_buf;
|
|
|
|
hw->hw_info.buffer_share_bit = 0;
|
|
hw->hw_info.buffer_unshare_reserve_bit = 0;
|
|
@@ -260,11 +264,11 @@ static int fjes_hw_setup(struct fjes_hw *hw)
|
|
|
|
result = fjes_hw_alloc_epbuf(&buf_pair->tx);
|
|
if (result)
|
|
- return result;
|
|
+ goto free_epbuf;
|
|
|
|
result = fjes_hw_alloc_epbuf(&buf_pair->rx);
|
|
if (result)
|
|
- return result;
|
|
+ goto free_epbuf;
|
|
|
|
spin_lock_irqsave(&hw->rx_status_lock, flags);
|
|
fjes_hw_setup_epbuf(&buf_pair->tx, mac,
|
|
@@ -287,6 +291,25 @@ static int fjes_hw_setup(struct fjes_hw *hw)
|
|
fjes_hw_init_command_registers(hw, ¶m);
|
|
|
|
return 0;
|
|
+
|
|
+free_epbuf:
|
|
+ for (epidx = 0; epidx < hw->max_epid ; epidx++) {
|
|
+ if (epidx == hw->my_epid)
|
|
+ continue;
|
|
+ fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].tx);
|
|
+ fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].rx);
|
|
+ }
|
|
+ fjes_hw_free_shared_status_region(hw);
|
|
+free_res_buf:
|
|
+ kfree(hw->hw_info.res_buf);
|
|
+ hw->hw_info.res_buf = NULL;
|
|
+free_req_buf:
|
|
+ kfree(hw->hw_info.req_buf);
|
|
+ hw->hw_info.req_buf = NULL;
|
|
+free_ep_info:
|
|
+ kfree(hw->ep_shm_info);
|
|
+ hw->ep_shm_info = NULL;
|
|
+ return result;
|
|
}
|
|
|
|
static void fjes_hw_cleanup(struct fjes_hw *hw)
|
|
diff --git drivers/net/gtp.c drivers/net/gtp.c
|
|
index d7bf8212ff04..a222736c3117 100644
|
|
--- drivers/net/gtp.c
|
|
+++ drivers/net/gtp.c
|
|
@@ -1380,26 +1380,26 @@ static int __init gtp_init(void)
|
|
|
|
get_random_bytes(>p_h_initval, sizeof(gtp_h_initval));
|
|
|
|
- err = rtnl_link_register(>p_link_ops);
|
|
+ err = register_pernet_subsys(>p_net_ops);
|
|
if (err < 0)
|
|
goto error_out;
|
|
|
|
- err = genl_register_family(>p_genl_family);
|
|
+ err = rtnl_link_register(>p_link_ops);
|
|
if (err < 0)
|
|
- goto unreg_rtnl_link;
|
|
+ goto unreg_pernet_subsys;
|
|
|
|
- err = register_pernet_subsys(>p_net_ops);
|
|
+ err = genl_register_family(>p_genl_family);
|
|
if (err < 0)
|
|
- goto unreg_genl_family;
|
|
+ goto unreg_rtnl_link;
|
|
|
|
pr_info("GTP module loaded (pdp ctx size %zd bytes)\n",
|
|
sizeof(struct pdp_ctx));
|
|
return 0;
|
|
|
|
-unreg_genl_family:
|
|
- genl_unregister_family(>p_genl_family);
|
|
unreg_rtnl_link:
|
|
rtnl_link_unregister(>p_link_ops);
|
|
+unreg_pernet_subsys:
|
|
+ unregister_pernet_subsys(>p_net_ops);
|
|
error_out:
|
|
pr_err("error loading GTP module loaded\n");
|
|
return err;
|
|
diff --git drivers/net/ppp/ppp_async.c drivers/net/ppp/ppp_async.c
|
|
index 297a986e6653..4d981d9e0e38 100644
|
|
--- drivers/net/ppp/ppp_async.c
|
|
+++ drivers/net/ppp/ppp_async.c
|
|
@@ -474,6 +474,10 @@ ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
|
|
case PPPIOCSMRU:
|
|
if (get_user(val, p))
|
|
break;
|
|
+ if (val > U16_MAX) {
|
|
+ err = -EINVAL;
|
|
+ break;
|
|
+ }
|
|
if (val < PPP_MRU)
|
|
val = PPP_MRU;
|
|
ap->mru = val;
|
|
diff --git drivers/net/usb/ax88172a.c drivers/net/usb/ax88172a.c
|
|
index 909755ef71ac..5881620e4436 100644
|
|
--- drivers/net/usb/ax88172a.c
|
|
+++ drivers/net/usb/ax88172a.c
|
|
@@ -198,7 +198,9 @@ static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
|
|
u8 buf[ETH_ALEN];
|
|
struct ax88172a_private *priv;
|
|
|
|
- usbnet_get_endpoints(dev, intf);
|
|
+ ret = usbnet_get_endpoints(dev, intf);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
|
if (!priv)
|
|
diff --git drivers/net/usb/dm9601.c drivers/net/usb/dm9601.c
|
|
index 5aad26600b03..9b7db5fd9e08 100644
|
|
--- drivers/net/usb/dm9601.c
|
|
+++ drivers/net/usb/dm9601.c
|
|
@@ -231,7 +231,7 @@ static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
|
|
err = dm_read_shared_word(dev, 1, loc, &res);
|
|
if (err < 0) {
|
|
netdev_err(dev->net, "MDIO read error: %d\n", err);
|
|
- return err;
|
|
+ return 0;
|
|
}
|
|
|
|
netdev_dbg(dev->net,
|
|
diff --git drivers/net/usb/lan78xx.c drivers/net/usb/lan78xx.c
|
|
index d6a71c051ec1..171accb5ebbf 100644
|
|
--- drivers/net/usb/lan78xx.c
|
|
+++ drivers/net/usb/lan78xx.c
|
|
@@ -2450,7 +2450,8 @@ static int lan78xx_reset(struct lan78xx_net *dev)
|
|
if (dev->chipid == ID_REV_CHIP_ID_7801_)
|
|
buf &= ~MAC_CR_GMII_EN_;
|
|
|
|
- if (dev->chipid == ID_REV_CHIP_ID_7800_) {
|
|
+ if (dev->chipid == ID_REV_CHIP_ID_7800_ ||
|
|
+ dev->chipid == ID_REV_CHIP_ID_7850_) {
|
|
ret = lan78xx_read_raw_eeprom(dev, 0, 1, &sig);
|
|
if (!ret && sig != EEPROM_INDICATOR) {
|
|
/* Implies there is no external eeprom. Set mac speed */
|
|
diff --git drivers/net/virtio_net.c drivers/net/virtio_net.c
|
|
index 067ebdd0d589..8e1a3c523b09 100644
|
|
--- drivers/net/virtio_net.c
|
|
+++ drivers/net/virtio_net.c
|
|
@@ -2277,10 +2277,11 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
|
|
{
|
|
vq_callback_t **callbacks;
|
|
struct virtqueue **vqs;
|
|
- int ret = -ENOMEM;
|
|
- int i, total_vqs;
|
|
const char **names;
|
|
+ int ret = -ENOMEM;
|
|
+ int total_vqs;
|
|
bool *ctx;
|
|
+ u16 i;
|
|
|
|
/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
|
|
* possible N-1 RX/TX queue pairs used in multiqueue mode, followed by
|
|
@@ -2317,8 +2318,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
|
|
for (i = 0; i < vi->max_queue_pairs; i++) {
|
|
callbacks[rxq2vq(i)] = skb_recv_done;
|
|
callbacks[txq2vq(i)] = skb_xmit_done;
|
|
- sprintf(vi->rq[i].name, "input.%d", i);
|
|
- sprintf(vi->sq[i].name, "output.%d", i);
|
|
+ sprintf(vi->rq[i].name, "input.%u", i);
|
|
+ sprintf(vi->sq[i].name, "output.%u", i);
|
|
names[rxq2vq(i)] = vi->rq[i].name;
|
|
names[txq2vq(i)] = vi->sq[i].name;
|
|
if (ctx)
|
|
diff --git drivers/net/wan/lmc/lmc_proto.c drivers/net/wan/lmc/lmc_proto.c
|
|
index f600075e84a2..7ae39a2b6340 100644
|
|
--- drivers/net/wan/lmc/lmc_proto.c
|
|
+++ drivers/net/wan/lmc/lmc_proto.c
|
|
@@ -103,17 +103,13 @@ __be16 lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/
|
|
switch(sc->if_type){
|
|
case LMC_PPP:
|
|
return hdlc_type_trans(skb, sc->lmc_device);
|
|
- break;
|
|
case LMC_NET:
|
|
return htons(ETH_P_802_2);
|
|
- break;
|
|
case LMC_RAW: /* Packet type for skbuff kind of useless */
|
|
return htons(ETH_P_802_2);
|
|
- break;
|
|
default:
|
|
printk(KERN_WARNING "%s: No protocol set for this interface, assuming 802.2 (which is wrong!!)\n", sc->name);
|
|
return htons(ETH_P_802_2);
|
|
- break;
|
|
}
|
|
lmc_trace(sc->lmc_device, "lmc_proto_tye out");
|
|
|
|
diff --git drivers/net/wireless/ath/ath9k/htc_drv_txrx.c drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
|
|
index e62ed7f42281..763521fca11d 100644
|
|
--- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
|
|
+++ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
|
|
@@ -647,9 +647,10 @@ void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event)
|
|
struct ath9k_htc_tx_event *tx_pend;
|
|
int i;
|
|
|
|
- for (i = 0; i < txs->cnt; i++) {
|
|
- WARN_ON(txs->cnt > HTC_MAX_TX_STATUS);
|
|
+ if (WARN_ON_ONCE(txs->cnt > HTC_MAX_TX_STATUS))
|
|
+ return;
|
|
|
|
+ for (i = 0; i < txs->cnt; i++) {
|
|
__txs = &txs->txstatus[i];
|
|
|
|
skb = ath9k_htc_tx_get_packet(priv, __txs);
|
|
diff --git drivers/net/wireless/marvell/libertas/Kconfig drivers/net/wireless/marvell/libertas/Kconfig
|
|
index e6268ceacbf1..28985cdac541 100644
|
|
--- drivers/net/wireless/marvell/libertas/Kconfig
|
|
+++ drivers/net/wireless/marvell/libertas/Kconfig
|
|
@@ -1,8 +1,6 @@
|
|
config LIBERTAS
|
|
tristate "Marvell 8xxx Libertas WLAN driver support"
|
|
depends on CFG80211
|
|
- select WIRELESS_EXT
|
|
- select WEXT_SPY
|
|
select LIB80211
|
|
select FW_LOADER
|
|
---help---
|
|
diff --git drivers/net/wireless/marvell/mwifiex/cfg80211.c drivers/net/wireless/marvell/mwifiex/cfg80211.c
|
|
index a88bddc38389..76205d6b2f9c 100644
|
|
--- drivers/net/wireless/marvell/mwifiex/cfg80211.c
|
|
+++ drivers/net/wireless/marvell/mwifiex/cfg80211.c
|
|
@@ -1940,6 +1940,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
|
|
|
mwifiex_set_sys_config_invalid_data(bss_cfg);
|
|
|
|
+ memcpy(bss_cfg->mac_addr, priv->curr_addr, ETH_ALEN);
|
|
+
|
|
if (params->beacon_interval)
|
|
bss_cfg->beacon_period = params->beacon_interval;
|
|
if (params->dtim_period)
|
|
diff --git drivers/net/wireless/marvell/mwifiex/fw.h drivers/net/wireless/marvell/mwifiex/fw.h
|
|
index c802b73a15c5..99b40bc6e7a6 100644
|
|
--- drivers/net/wireless/marvell/mwifiex/fw.h
|
|
+++ drivers/net/wireless/marvell/mwifiex/fw.h
|
|
@@ -168,6 +168,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|
#define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32)
|
|
#define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35)
|
|
#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42)
|
|
+#define TLV_TYPE_UAP_MAC_ADDRESS (PROPRIETARY_TLV_BASE_ID + 43)
|
|
#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44)
|
|
#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45)
|
|
#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48)
|
|
diff --git drivers/net/wireless/marvell/mwifiex/ioctl.h drivers/net/wireless/marvell/mwifiex/ioctl.h
|
|
index 0dd592ea6e83..96ff91655a77 100644
|
|
--- drivers/net/wireless/marvell/mwifiex/ioctl.h
|
|
+++ drivers/net/wireless/marvell/mwifiex/ioctl.h
|
|
@@ -119,6 +119,7 @@ struct mwifiex_uap_bss_param {
|
|
u8 qos_info;
|
|
u8 power_constraint;
|
|
struct mwifiex_types_wmm_info wmm_info;
|
|
+ u8 mac_addr[ETH_ALEN];
|
|
};
|
|
|
|
enum {
|
|
diff --git drivers/net/wireless/marvell/mwifiex/uap_cmd.c drivers/net/wireless/marvell/mwifiex/uap_cmd.c
|
|
index 0939a8c8f3ab..1ab253c97c14 100644
|
|
--- drivers/net/wireless/marvell/mwifiex/uap_cmd.c
|
|
+++ drivers/net/wireless/marvell/mwifiex/uap_cmd.c
|
|
@@ -479,6 +479,7 @@ void mwifiex_config_uap_11d(struct mwifiex_private *priv,
|
|
static int
|
|
mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
|
|
{
|
|
+ struct host_cmd_tlv_mac_addr *mac_tlv;
|
|
struct host_cmd_tlv_dtim_period *dtim_period;
|
|
struct host_cmd_tlv_beacon_period *beacon_period;
|
|
struct host_cmd_tlv_ssid *ssid;
|
|
@@ -498,6 +499,13 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
|
|
int i;
|
|
u16 cmd_size = *param_size;
|
|
|
|
+ mac_tlv = (struct host_cmd_tlv_mac_addr *)tlv;
|
|
+ mac_tlv->header.type = cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
|
|
+ mac_tlv->header.len = cpu_to_le16(ETH_ALEN);
|
|
+ memcpy(mac_tlv->mac_addr, bss_cfg->mac_addr, ETH_ALEN);
|
|
+ cmd_size += sizeof(struct host_cmd_tlv_mac_addr);
|
|
+ tlv += sizeof(struct host_cmd_tlv_mac_addr);
|
|
+
|
|
if (bss_cfg->ssid.ssid_len) {
|
|
ssid = (struct host_cmd_tlv_ssid *)tlv;
|
|
ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
|
|
diff --git drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
|
|
index bfd704b17a44..9263a6a64788 100644
|
|
--- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
|
|
+++ drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
|
|
@@ -6366,6 +6366,18 @@ static const struct usb_device_id dev_table[] = {
|
|
.driver_info = (unsigned long)&rtl8192eu_fops},
|
|
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818c, 0xff, 0xff, 0xff),
|
|
.driver_info = (unsigned long)&rtl8192eu_fops},
|
|
+/* D-Link DWA-131 rev C1 */
|
|
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3312, 0xff, 0xff, 0xff),
|
|
+ .driver_info = (unsigned long)&rtl8192eu_fops},
|
|
+/* TP-Link TL-WN8200ND V2 */
|
|
+{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0126, 0xff, 0xff, 0xff),
|
|
+ .driver_info = (unsigned long)&rtl8192eu_fops},
|
|
+/* Mercusys MW300UM */
|
|
+{USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0100, 0xff, 0xff, 0xff),
|
|
+ .driver_info = (unsigned long)&rtl8192eu_fops},
|
|
+/* Mercusys MW300UH */
|
|
+{USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0104, 0xff, 0xff, 0xff),
|
|
+ .driver_info = (unsigned long)&rtl8192eu_fops},
|
|
#endif
|
|
{ }
|
|
};
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/pci.c drivers/net/wireless/realtek/rtlwifi/pci.c
|
|
index ab74f3155854..b6c3a6d422ea 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/pci.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/pci.c
|
|
@@ -194,21 +194,29 @@ static bool _rtl_pci_platform_switch_device_pci_aspm(
|
|
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
|
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
|
|
|
+ value &= PCI_EXP_LNKCTL_ASPMC;
|
|
+
|
|
if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)
|
|
- value |= 0x40;
|
|
+ value |= PCI_EXP_LNKCTL_CCC;
|
|
|
|
- pci_write_config_byte(rtlpci->pdev, 0x80, value);
|
|
+ pcie_capability_clear_and_set_word(rtlpci->pdev, PCI_EXP_LNKCTL,
|
|
+ PCI_EXP_LNKCTL_ASPMC | value,
|
|
+ value);
|
|
|
|
return false;
|
|
}
|
|
|
|
-/*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/
|
|
-static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value)
|
|
+/* @value is PCI_EXP_LNKCTL_CLKREQ_EN or 0 to enable/disable clk request. */
|
|
+static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u16 value)
|
|
{
|
|
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
|
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
|
|
|
- pci_write_config_byte(rtlpci->pdev, 0x81, value);
|
|
+ value &= PCI_EXP_LNKCTL_CLKREQ_EN;
|
|
+
|
|
+ pcie_capability_clear_and_set_word(rtlpci->pdev, PCI_EXP_LNKCTL,
|
|
+ PCI_EXP_LNKCTL_CLKREQ_EN,
|
|
+ value);
|
|
|
|
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE)
|
|
udelay(100);
|
|
@@ -222,11 +230,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
|
|
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
|
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
|
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
|
|
- u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
|
|
/*Retrieve original configuration settings. */
|
|
u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg;
|
|
- u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter.
|
|
- pcibridge_linkctrlreg;
|
|
u16 aspmlevel = 0;
|
|
u8 tmp_u1b = 0;
|
|
|
|
@@ -251,16 +256,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
|
|
/*Set corresponding value. */
|
|
aspmlevel |= BIT(0) | BIT(1);
|
|
linkctrl_reg &= ~aspmlevel;
|
|
- pcibridge_linkctrlreg &= ~(BIT(0) | BIT(1));
|
|
|
|
_rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg);
|
|
- udelay(50);
|
|
-
|
|
- /*4 Disable Pci Bridge ASPM */
|
|
- pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
|
|
- pcibridge_linkctrlreg);
|
|
-
|
|
- udelay(50);
|
|
}
|
|
|
|
/*
|
|
@@ -276,9 +273,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
|
|
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
|
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
|
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
|
|
- u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
|
|
u16 aspmlevel;
|
|
- u8 u_pcibridge_aspmsetting;
|
|
u8 u_device_aspmsetting;
|
|
|
|
if (!ppsc->support_aspm)
|
|
@@ -290,25 +285,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
|
|
return;
|
|
}
|
|
|
|
- /*4 Enable Pci Bridge ASPM */
|
|
-
|
|
- u_pcibridge_aspmsetting =
|
|
- pcipriv->ndis_adapter.pcibridge_linkctrlreg |
|
|
- rtlpci->const_hostpci_aspm_setting;
|
|
-
|
|
- if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
|
|
- u_pcibridge_aspmsetting &= ~BIT(0);
|
|
-
|
|
- pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
|
|
- u_pcibridge_aspmsetting);
|
|
-
|
|
- RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
|
- "PlatformEnableASPM(): Write reg[%x] = %x\n",
|
|
- (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10),
|
|
- u_pcibridge_aspmsetting);
|
|
-
|
|
- udelay(50);
|
|
-
|
|
/*Get ASPM level (with/without Clock Req) */
|
|
aspmlevel = rtlpci->const_devicepci_aspm_setting;
|
|
u_device_aspmsetting = pcipriv->ndis_adapter.linkctrl_reg;
|
|
@@ -322,7 +298,8 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
|
|
|
|
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) {
|
|
_rtl_pci_switch_clk_req(hw, (ppsc->reg_rfps_level &
|
|
- RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0);
|
|
+ RT_RF_OFF_LEVL_CLK_REQ) ?
|
|
+ PCI_EXP_LNKCTL_CLKREQ_EN : 0);
|
|
RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ);
|
|
}
|
|
udelay(100);
|
|
@@ -390,22 +367,6 @@ static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw,
|
|
return find_buddy_priv;
|
|
}
|
|
|
|
-static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
|
|
-{
|
|
- struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
|
- struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
|
|
- u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset;
|
|
- u8 linkctrl_reg;
|
|
- u8 num4bbytes;
|
|
-
|
|
- num4bbytes = (capabilityoffset + 0x10) / 4;
|
|
-
|
|
- /*Read Link Control Register */
|
|
- pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg);
|
|
-
|
|
- pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg;
|
|
-}
|
|
-
|
|
static void rtl_pci_parse_configuration(struct pci_dev *pdev,
|
|
struct ieee80211_hw *hw)
|
|
{
|
|
@@ -2076,12 +2037,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
|
PCI_SLOT(bridge_pdev->devfn);
|
|
pcipriv->ndis_adapter.pcibridge_funcnum =
|
|
PCI_FUNC(bridge_pdev->devfn);
|
|
- pcipriv->ndis_adapter.pcibridge_pciehdr_offset =
|
|
- pci_pcie_cap(bridge_pdev);
|
|
- pcipriv->ndis_adapter.num4bytes =
|
|
- (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4;
|
|
-
|
|
- rtl_pci_get_linkcontrol_field(hw);
|
|
|
|
if (pcipriv->ndis_adapter.pcibridge_vendor ==
|
|
PCI_BRIDGE_VENDOR_AMD) {
|
|
@@ -2098,13 +2053,11 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
|
pdev->vendor, pcipriv->ndis_adapter.linkctrl_reg);
|
|
|
|
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
|
|
- "pci_bridge busnumber:devnumber:funcnumber:vendor:pcie_cap:link_ctl_reg:amd %d:%d:%d:%x:%x:%x:%x\n",
|
|
+ "pci_bridge busnumber:devnumber:funcnumber:vendor:amd %d:%d:%d:%x:%x\n",
|
|
pcipriv->ndis_adapter.pcibridge_busnum,
|
|
pcipriv->ndis_adapter.pcibridge_devnum,
|
|
pcipriv->ndis_adapter.pcibridge_funcnum,
|
|
pcibridge_vendors[pcipriv->ndis_adapter.pcibridge_vendor],
|
|
- pcipriv->ndis_adapter.pcibridge_pciehdr_offset,
|
|
- pcipriv->ndis_adapter.pcibridge_linkctrlreg,
|
|
pcipriv->ndis_adapter.amd_l1_patch);
|
|
|
|
rtl_pci_parse_configuration(pdev, hw);
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/pci.h drivers/net/wireless/realtek/rtlwifi/pci.h
|
|
index d9039ea10ba4..19b7a57313da 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/pci.h
|
|
+++ drivers/net/wireless/realtek/rtlwifi/pci.h
|
|
@@ -262,11 +262,6 @@ struct mp_adapter {
|
|
u16 pcibridge_vendorid;
|
|
u16 pcibridge_deviceid;
|
|
|
|
- u8 num4bytes;
|
|
-
|
|
- u8 pcibridge_pciehdr_offset;
|
|
- u8 pcibridge_linkctrlreg;
|
|
-
|
|
bool amd_l1_patch;
|
|
};
|
|
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
|
|
index 14a256062614..44cabfa1ca27 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
|
|
@@ -38,7 +38,6 @@ static u32 _rtl88e_phy_rf_serial_read(struct ieee80211_hw *hw,
|
|
static void _rtl88e_phy_rf_serial_write(struct ieee80211_hw *hw,
|
|
enum radio_path rfpath, u32 offset,
|
|
u32 data);
|
|
-static u32 _rtl88e_phy_calculate_bit_shift(u32 bitmask);
|
|
static bool _rtl88e_phy_bb8188e_config_parafile(struct ieee80211_hw *hw);
|
|
static bool _rtl88e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
|
|
static bool phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
|
|
@@ -68,7 +67,7 @@ u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
|
|
"regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask);
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl88e_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
returnvalue = (originalvalue & bitmask) >> bitshift;
|
|
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
|
|
@@ -91,7 +90,7 @@ void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw,
|
|
|
|
if (bitmask != MASKDWORD) {
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl88e_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = ((originalvalue & (~bitmask)) | (data << bitshift));
|
|
}
|
|
|
|
@@ -117,7 +116,7 @@ u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw,
|
|
|
|
|
|
original_value = _rtl88e_phy_rf_serial_read(hw, rfpath, regaddr);
|
|
- bitshift = _rtl88e_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
readback_value = (original_value & bitmask) >> bitshift;
|
|
|
|
spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
|
|
@@ -146,7 +145,7 @@ void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|
original_value = _rtl88e_phy_rf_serial_read(hw,
|
|
rfpath,
|
|
regaddr);
|
|
- bitshift = _rtl88e_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data =
|
|
((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
@@ -232,17 +231,6 @@ static void _rtl88e_phy_rf_serial_write(struct ieee80211_hw *hw,
|
|
rfpath, pphyreg->rf3wire_offset, data_and_addr);
|
|
}
|
|
|
|
-static u32 _rtl88e_phy_calculate_bit_shift(u32 bitmask)
|
|
-{
|
|
- u32 i;
|
|
-
|
|
- for (i = 0; i <= 31; i++) {
|
|
- if (((bitmask >> i) & 0x1) == 1)
|
|
- break;
|
|
- }
|
|
- return i;
|
|
-}
|
|
-
|
|
bool rtl88e_phy_mac_config(struct ieee80211_hw *hw)
|
|
{
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
|
|
index 7c6e5d91439d..bc2b3849828d 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
|
|
@@ -39,7 +39,7 @@ u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n",
|
|
regaddr, bitmask);
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
returnvalue = (originalvalue & bitmask) >> bitshift;
|
|
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
|
|
@@ -62,7 +62,7 @@ void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw,
|
|
|
|
if (bitmask != MASKDWORD) {
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = ((originalvalue & (~bitmask)) | (data << bitshift));
|
|
}
|
|
|
|
@@ -165,18 +165,6 @@ void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
|
|
}
|
|
EXPORT_SYMBOL(_rtl92c_phy_rf_serial_write);
|
|
|
|
-u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask)
|
|
-{
|
|
- u32 i;
|
|
-
|
|
- for (i = 0; i <= 31; i++) {
|
|
- if (((bitmask >> i) & 0x1) == 1)
|
|
- break;
|
|
- }
|
|
- return i;
|
|
-}
|
|
-EXPORT_SYMBOL(_rtl92c_phy_calculate_bit_shift);
|
|
-
|
|
static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw)
|
|
{
|
|
rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
|
|
index d11261e05a2e..76f574047c62 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
|
|
@@ -218,7 +218,6 @@ bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw,
|
|
void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw);
|
|
void rtl92c_phy_set_io(struct ieee80211_hw *hw);
|
|
void rtl92c_bb_block_on(struct ieee80211_hw *hw);
|
|
-u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
|
|
long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
|
|
enum wireless_mode wirelessmode,
|
|
u8 txpwridx);
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
|
|
index 7c6d7fc1ef9a..9f478d8af804 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
|
|
@@ -61,7 +61,7 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
|
|
rfpath, regaddr);
|
|
}
|
|
|
|
- bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
readback_value = (original_value & bitmask) >> bitshift;
|
|
|
|
spin_unlock(&rtlpriv->locks.rf_lock);
|
|
@@ -132,7 +132,7 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|
original_value = _rtl92c_phy_rf_serial_read(hw,
|
|
rfpath,
|
|
regaddr);
|
|
- bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data =
|
|
((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
@@ -144,7 +144,7 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|
original_value = _rtl92c_phy_fw_rf_serial_read(hw,
|
|
rfpath,
|
|
regaddr);
|
|
- bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data =
|
|
((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
|
|
index 93f3bc0197b4..e084a91e26d9 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
|
|
@@ -116,7 +116,6 @@ u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath,
|
|
u32 offset);
|
|
u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
|
|
enum radio_path rfpath, u32 offset);
|
|
-u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
|
|
void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
|
|
enum radio_path rfpath, u32 offset, u32 data);
|
|
void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
|
|
index f068dd5317a7..5a5476a2dc2f 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
|
|
@@ -54,7 +54,7 @@ u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
|
|
original_value = _rtl92c_phy_fw_rf_serial_read(hw,
|
|
rfpath, regaddr);
|
|
}
|
|
- bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
readback_value = (original_value & bitmask) >> bitshift;
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
|
|
"regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
|
|
@@ -78,7 +78,7 @@ void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|
original_value = _rtl92c_phy_rf_serial_read(hw,
|
|
rfpath,
|
|
regaddr);
|
|
- bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data =
|
|
((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
@@ -89,7 +89,7 @@ void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|
original_value = _rtl92c_phy_fw_rf_serial_read(hw,
|
|
rfpath,
|
|
regaddr);
|
|
- bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data =
|
|
((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
|
|
index 53734250479c..2ee779614269 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
|
|
@@ -182,17 +182,14 @@ static u32 targetchnl_2g[TARGET_CHNL_NUM_2G] = {
|
|
25711, 25658, 25606, 25554, 25502, 25451, 25328
|
|
};
|
|
|
|
-static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask)
|
|
-{
|
|
- u32 i;
|
|
-
|
|
- for (i = 0; i <= 31; i++) {
|
|
- if (((bitmask >> i) & 0x1) == 1)
|
|
- break;
|
|
- }
|
|
-
|
|
- return i;
|
|
-}
|
|
+static const u8 channel_all[59] = {
|
|
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
|
|
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
|
|
+ 114, 116, 118, 120, 122, 124, 126, 128, 130,
|
|
+ 132, 134, 136, 138, 140, 149, 151, 153, 155,
|
|
+ 157, 159, 161, 163, 165
|
|
+};
|
|
|
|
u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
|
|
{
|
|
@@ -216,7 +213,7 @@ u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
|
|
} else {
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
}
|
|
- bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
returnvalue = (originalvalue & bitmask) >> bitshift;
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
|
|
"BBR MASK=0x%x Addr[0x%x]=0x%x\n",
|
|
@@ -248,7 +245,7 @@ void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw,
|
|
dbi_direct);
|
|
else
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = ((originalvalue & (~bitmask)) | (data << bitshift));
|
|
}
|
|
if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob)
|
|
@@ -336,7 +333,7 @@ u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw,
|
|
regaddr, rfpath, bitmask);
|
|
spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
|
|
original_value = _rtl92d_phy_rf_serial_read(hw, rfpath, regaddr);
|
|
- bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
readback_value = (original_value & bitmask) >> bitshift;
|
|
spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
|
|
@@ -363,7 +360,7 @@ void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
|
|
if (bitmask != RFREG_OFFSET_MASK) {
|
|
original_value = _rtl92d_phy_rf_serial_read(hw,
|
|
rfpath, regaddr);
|
|
- bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = ((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
}
|
|
@@ -1383,14 +1380,6 @@ static void _rtl92d_phy_switch_rf_setting(struct ieee80211_hw *hw, u8 channel)
|
|
|
|
u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl)
|
|
{
|
|
- u8 channel_all[59] = {
|
|
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
- 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
|
|
- 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
|
|
- 114, 116, 118, 120, 122, 124, 126, 128, 130,
|
|
- 132, 134, 136, 138, 140, 149, 151, 153, 155,
|
|
- 157, 159, 161, 163, 165
|
|
- };
|
|
u8 place = chnl;
|
|
|
|
if (chnl > 14) {
|
|
@@ -3245,37 +3234,28 @@ void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw)
|
|
u8 rtl92d_get_chnlgroup_fromarray(u8 chnl)
|
|
{
|
|
u8 group;
|
|
- u8 channel_info[59] = {
|
|
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
- 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56,
|
|
- 58, 60, 62, 64, 100, 102, 104, 106, 108,
|
|
- 110, 112, 114, 116, 118, 120, 122, 124,
|
|
- 126, 128, 130, 132, 134, 136, 138, 140,
|
|
- 149, 151, 153, 155, 157, 159, 161, 163,
|
|
- 165
|
|
- };
|
|
|
|
- if (channel_info[chnl] <= 3)
|
|
+ if (channel_all[chnl] <= 3)
|
|
group = 0;
|
|
- else if (channel_info[chnl] <= 9)
|
|
+ else if (channel_all[chnl] <= 9)
|
|
group = 1;
|
|
- else if (channel_info[chnl] <= 14)
|
|
+ else if (channel_all[chnl] <= 14)
|
|
group = 2;
|
|
- else if (channel_info[chnl] <= 44)
|
|
+ else if (channel_all[chnl] <= 44)
|
|
group = 3;
|
|
- else if (channel_info[chnl] <= 54)
|
|
+ else if (channel_all[chnl] <= 54)
|
|
group = 4;
|
|
- else if (channel_info[chnl] <= 64)
|
|
+ else if (channel_all[chnl] <= 64)
|
|
group = 5;
|
|
- else if (channel_info[chnl] <= 112)
|
|
+ else if (channel_all[chnl] <= 112)
|
|
group = 6;
|
|
- else if (channel_info[chnl] <= 126)
|
|
+ else if (channel_all[chnl] <= 126)
|
|
group = 7;
|
|
- else if (channel_info[chnl] <= 140)
|
|
+ else if (channel_all[chnl] <= 140)
|
|
group = 8;
|
|
- else if (channel_info[chnl] <= 153)
|
|
+ else if (channel_all[chnl] <= 153)
|
|
group = 9;
|
|
- else if (channel_info[chnl] <= 159)
|
|
+ else if (channel_all[chnl] <= 159)
|
|
group = 10;
|
|
else
|
|
group = 11;
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
|
|
index 8b072ee8e0d5..9a3e88d6a570 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
|
|
@@ -38,7 +38,6 @@ static u32 _rtl92ee_phy_rf_serial_read(struct ieee80211_hw *hw,
|
|
static void _rtl92ee_phy_rf_serial_write(struct ieee80211_hw *hw,
|
|
enum radio_path rfpath, u32 offset,
|
|
u32 data);
|
|
-static u32 _rtl92ee_phy_calculate_bit_shift(u32 bitmask);
|
|
static bool _rtl92ee_phy_bb8192ee_config_parafile(struct ieee80211_hw *hw);
|
|
static bool _rtl92ee_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
|
|
static bool phy_config_bb_with_hdr_file(struct ieee80211_hw *hw,
|
|
@@ -68,7 +67,7 @@ u32 rtl92ee_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
|
|
"regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask);
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
returnvalue = (originalvalue & bitmask) >> bitshift;
|
|
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
|
|
@@ -90,7 +89,7 @@ void rtl92ee_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr,
|
|
|
|
if (bitmask != MASKDWORD) {
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = ((originalvalue & (~bitmask)) | (data << bitshift));
|
|
}
|
|
|
|
@@ -115,7 +114,7 @@ u32 rtl92ee_phy_query_rf_reg(struct ieee80211_hw *hw,
|
|
spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
|
|
|
|
original_value = _rtl92ee_phy_rf_serial_read(hw , rfpath, regaddr);
|
|
- bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
readback_value = (original_value & bitmask) >> bitshift;
|
|
|
|
spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
|
|
@@ -143,7 +142,7 @@ void rtl92ee_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|
|
|
if (bitmask != RFREG_OFFSET_MASK) {
|
|
original_value = _rtl92ee_phy_rf_serial_read(hw, rfpath, addr);
|
|
- bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = (original_value & (~bitmask)) | (data << bitshift);
|
|
}
|
|
|
|
@@ -226,17 +225,6 @@ static void _rtl92ee_phy_rf_serial_write(struct ieee80211_hw *hw,
|
|
pphyreg->rf3wire_offset, data_and_addr);
|
|
}
|
|
|
|
-static u32 _rtl92ee_phy_calculate_bit_shift(u32 bitmask)
|
|
-{
|
|
- u32 i;
|
|
-
|
|
- for (i = 0; i <= 31; i++) {
|
|
- if (((bitmask >> i) & 0x1) == 1)
|
|
- break;
|
|
- }
|
|
- return i;
|
|
-}
|
|
-
|
|
bool rtl92ee_phy_mac_config(struct ieee80211_hw *hw)
|
|
{
|
|
return _rtl92ee_phy_config_mac_with_headerfile(hw);
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
|
|
index 86cb853f7169..0430a3b823d6 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
|
|
@@ -36,18 +36,6 @@
|
|
#include "hw.h"
|
|
#include "table.h"
|
|
|
|
-static u32 _rtl92s_phy_calculate_bit_shift(u32 bitmask)
|
|
-{
|
|
- u32 i;
|
|
-
|
|
- for (i = 0; i <= 31; i++) {
|
|
- if (((bitmask >> i) & 0x1) == 1)
|
|
- break;
|
|
- }
|
|
-
|
|
- return i;
|
|
-}
|
|
-
|
|
u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
|
|
{
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
@@ -57,7 +45,7 @@ u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
|
|
regaddr, bitmask);
|
|
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
returnvalue = (originalvalue & bitmask) >> bitshift;
|
|
|
|
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "BBR MASK=0x%x Addr[0x%x]=0x%x\n",
|
|
@@ -79,7 +67,7 @@ void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
|
|
|
|
if (bitmask != MASKDWORD) {
|
|
originalvalue = rtl_read_dword(rtlpriv, regaddr);
|
|
- bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = ((originalvalue & (~bitmask)) | (data << bitshift));
|
|
}
|
|
|
|
@@ -187,7 +175,7 @@ u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
|
|
|
|
original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr);
|
|
|
|
- bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
readback_value = (original_value & bitmask) >> bitshift;
|
|
|
|
spin_unlock(&rtlpriv->locks.rf_lock);
|
|
@@ -218,7 +206,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
|
|
if (bitmask != RFREG_OFFSET_MASK) {
|
|
original_value = _rtl92s_phy_rf_serial_read(hw, rfpath,
|
|
regaddr);
|
|
- bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = ((original_value & (~bitmask)) | (data << bitshift));
|
|
}
|
|
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
|
|
index 5cf29f5a4b54..e6ac496e898e 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
|
|
@@ -72,7 +72,7 @@ u32 rtl8723e_phy_query_rf_reg(struct ieee80211_hw *hw,
|
|
rfpath, regaddr);
|
|
}
|
|
|
|
- bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
readback_value = (original_value & bitmask) >> bitshift;
|
|
|
|
spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
|
|
@@ -104,7 +104,7 @@ void rtl8723e_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|
original_value = rtl8723_phy_rf_serial_read(hw,
|
|
rfpath,
|
|
regaddr);
|
|
- bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data =
|
|
((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
@@ -113,7 +113,7 @@ void rtl8723e_phy_set_rf_reg(struct ieee80211_hw *hw,
|
|
rtl8723_phy_rf_serial_write(hw, rfpath, regaddr, data);
|
|
} else {
|
|
if (bitmask != RFREG_OFFSET_MASK) {
|
|
- bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data =
|
|
((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
|
|
index 9606641519e7..f1b42f9d6cd1 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
|
|
@@ -63,7 +63,7 @@ u32 rtl8723be_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
|
|
spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
|
|
|
|
original_value = rtl8723_phy_rf_serial_read(hw, rfpath, regaddr);
|
|
- bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
readback_value = (original_value & bitmask) >> bitshift;
|
|
|
|
spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
|
|
@@ -91,7 +91,7 @@ void rtl8723be_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path path,
|
|
if (bitmask != RFREG_OFFSET_MASK) {
|
|
original_value = rtl8723_phy_rf_serial_read(hw, path,
|
|
regaddr);
|
|
- bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
|
|
+ bitshift = calculate_bit_shift(bitmask);
|
|
data = ((original_value & (~bitmask)) |
|
|
(data << bitshift));
|
|
}
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
|
|
index 43d24e1ee5e6..af9cd74e09d4 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
|
|
@@ -75,13 +75,9 @@ EXPORT_SYMBOL_GPL(rtl8723_phy_set_bb_reg);
|
|
|
|
u32 rtl8723_phy_calculate_bit_shift(u32 bitmask)
|
|
{
|
|
- u32 i;
|
|
+ u32 i = ffs(bitmask);
|
|
|
|
- for (i = 0; i <= 31; i++) {
|
|
- if (((bitmask >> i) & 0x1) == 1)
|
|
- break;
|
|
- }
|
|
- return i;
|
|
+ return i ? i - 1 : 32;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtl8723_phy_calculate_bit_shift);
|
|
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
|
|
index 176deb2b5386..f96d823e7f14 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
|
|
+++ drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
|
|
@@ -49,7 +49,13 @@ static u32 _rtl8821ae_phy_rf_serial_read(struct ieee80211_hw *hw,
|
|
static void _rtl8821ae_phy_rf_serial_write(struct ieee80211_hw *hw,
|
|
enum radio_path rfpath, u32 offset,
|
|
u32 data);
|
|
-static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask);
|
|
+static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask)
|
|
+{
|
|
+ if (WARN_ON_ONCE(!bitmask))
|
|
+ return 0;
|
|
+
|
|
+ return __ffs(bitmask);
|
|
+}
|
|
static bool _rtl8821ae_phy_bb8821a_config_parafile(struct ieee80211_hw *hw);
|
|
/*static bool _rtl8812ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);*/
|
|
static bool _rtl8821ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
|
|
@@ -296,17 +302,6 @@ static void _rtl8821ae_phy_rf_serial_write(struct ieee80211_hw *hw,
|
|
rfpath, pphyreg->rf3wire_offset, data_and_addr);
|
|
}
|
|
|
|
-static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask)
|
|
-{
|
|
- u32 i;
|
|
-
|
|
- for (i = 0; i <= 31; i++) {
|
|
- if (((bitmask >> i) & 0x1) == 1)
|
|
- break;
|
|
- }
|
|
- return i;
|
|
-}
|
|
-
|
|
bool rtl8821ae_phy_mac_config(struct ieee80211_hw *hw)
|
|
{
|
|
bool rtstatus = 0;
|
|
diff --git drivers/net/wireless/realtek/rtlwifi/wifi.h drivers/net/wireless/realtek/rtlwifi/wifi.h
|
|
index c73ce334ce6c..61f5b6fc1754 100644
|
|
--- drivers/net/wireless/realtek/rtlwifi/wifi.h
|
|
+++ drivers/net/wireless/realtek/rtlwifi/wifi.h
|
|
@@ -3095,4 +3095,11 @@ static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw,
|
|
return ieee80211_find_sta(mac->vif, mac_addr);
|
|
}
|
|
|
|
+static inline u32 calculate_bit_shift(u32 bitmask)
|
|
+{
|
|
+ if (WARN_ON_ONCE(!bitmask))
|
|
+ return 0;
|
|
+
|
|
+ return __ffs(bitmask);
|
|
+}
|
|
#endif
|
|
diff --git drivers/net/xen-netback/netback.c drivers/net/xen-netback/netback.c
|
|
index 47e7e9aab9cf..901ddea37da6 100644
|
|
--- drivers/net/xen-netback/netback.c
|
|
+++ drivers/net/xen-netback/netback.c
|
|
@@ -97,13 +97,12 @@ module_param_named(hash_cache_size, xenvif_hash_cache_size, uint, 0644);
|
|
MODULE_PARM_DESC(hash_cache_size, "Number of flows in the hash cache");
|
|
|
|
static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
|
|
- u8 status);
|
|
+ s8 status);
|
|
|
|
static void make_tx_response(struct xenvif_queue *queue,
|
|
- struct xen_netif_tx_request *txp,
|
|
+ const struct xen_netif_tx_request *txp,
|
|
unsigned int extra_count,
|
|
- s8 st);
|
|
-static void push_tx_responses(struct xenvif_queue *queue);
|
|
+ s8 status);
|
|
|
|
static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx);
|
|
|
|
@@ -201,13 +200,9 @@ static void xenvif_tx_err(struct xenvif_queue *queue,
|
|
unsigned int extra_count, RING_IDX end)
|
|
{
|
|
RING_IDX cons = queue->tx.req_cons;
|
|
- unsigned long flags;
|
|
|
|
do {
|
|
- spin_lock_irqsave(&queue->response_lock, flags);
|
|
make_tx_response(queue, txp, extra_count, XEN_NETIF_RSP_ERROR);
|
|
- push_tx_responses(queue);
|
|
- spin_unlock_irqrestore(&queue->response_lock, flags);
|
|
if (cons == end)
|
|
break;
|
|
RING_COPY_REQUEST(&queue->tx, cons++, txp);
|
|
@@ -456,12 +451,20 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
|
|
}
|
|
|
|
for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
|
|
- shinfo->nr_frags++, gop++, nr_slots--) {
|
|
+ nr_slots--) {
|
|
+ if (unlikely(!txp->size)) {
|
|
+ make_tx_response(queue, txp, 0, XEN_NETIF_RSP_OKAY);
|
|
+ ++txp;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
index = pending_index(queue->pending_cons++);
|
|
pending_idx = queue->pending_ring[index];
|
|
xenvif_tx_create_map_op(queue, pending_idx, txp,
|
|
txp == first ? extra_count : 0, gop);
|
|
frag_set_pending_idx(&frags[shinfo->nr_frags], pending_idx);
|
|
+ ++shinfo->nr_frags;
|
|
+ ++gop;
|
|
|
|
if (txp == first)
|
|
txp = txfrags;
|
|
@@ -474,20 +477,33 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
|
|
shinfo = skb_shinfo(nskb);
|
|
frags = shinfo->frags;
|
|
|
|
- for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
|
|
- shinfo->nr_frags++, txp++, gop++) {
|
|
+ for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; ++txp) {
|
|
+ if (unlikely(!txp->size)) {
|
|
+ make_tx_response(queue, txp, 0,
|
|
+ XEN_NETIF_RSP_OKAY);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
index = pending_index(queue->pending_cons++);
|
|
pending_idx = queue->pending_ring[index];
|
|
xenvif_tx_create_map_op(queue, pending_idx, txp, 0,
|
|
gop);
|
|
frag_set_pending_idx(&frags[shinfo->nr_frags],
|
|
pending_idx);
|
|
+ ++shinfo->nr_frags;
|
|
+ ++gop;
|
|
+ }
|
|
+
|
|
+ if (shinfo->nr_frags) {
|
|
+ skb_shinfo(skb)->frag_list = nskb;
|
|
+ nskb = NULL;
|
|
}
|
|
+ }
|
|
|
|
- skb_shinfo(skb)->frag_list = nskb;
|
|
- } else if (nskb) {
|
|
+ if (nskb) {
|
|
/* A frag_list skb was allocated but it is no longer needed
|
|
- * because enough slots were converted to copy ops above.
|
|
+ * because enough slots were converted to copy ops above or some
|
|
+ * were empty.
|
|
*/
|
|
kfree_skb(nskb);
|
|
}
|
|
@@ -960,7 +976,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
|
|
(ret == 0) ?
|
|
XEN_NETIF_RSP_OKAY :
|
|
XEN_NETIF_RSP_ERROR);
|
|
- push_tx_responses(queue);
|
|
continue;
|
|
}
|
|
|
|
@@ -972,7 +987,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
|
|
|
|
make_tx_response(queue, &txreq, extra_count,
|
|
XEN_NETIF_RSP_OKAY);
|
|
- push_tx_responses(queue);
|
|
continue;
|
|
}
|
|
|
|
@@ -1398,8 +1412,35 @@ int xenvif_tx_action(struct xenvif_queue *queue, int budget)
|
|
return work_done;
|
|
}
|
|
|
|
+static void _make_tx_response(struct xenvif_queue *queue,
|
|
+ const struct xen_netif_tx_request *txp,
|
|
+ unsigned int extra_count,
|
|
+ s8 status)
|
|
+{
|
|
+ RING_IDX i = queue->tx.rsp_prod_pvt;
|
|
+ struct xen_netif_tx_response *resp;
|
|
+
|
|
+ resp = RING_GET_RESPONSE(&queue->tx, i);
|
|
+ resp->id = txp->id;
|
|
+ resp->status = status;
|
|
+
|
|
+ while (extra_count-- != 0)
|
|
+ RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL;
|
|
+
|
|
+ queue->tx.rsp_prod_pvt = ++i;
|
|
+}
|
|
+
|
|
+static void push_tx_responses(struct xenvif_queue *queue)
|
|
+{
|
|
+ int notify;
|
|
+
|
|
+ RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
|
|
+ if (notify)
|
|
+ notify_remote_via_irq(queue->tx_irq);
|
|
+}
|
|
+
|
|
static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
|
|
- u8 status)
|
|
+ s8 status)
|
|
{
|
|
struct pending_tx_info *pending_tx_info;
|
|
pending_ring_idx_t index;
|
|
@@ -1409,8 +1450,8 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
|
|
|
|
spin_lock_irqsave(&queue->response_lock, flags);
|
|
|
|
- make_tx_response(queue, &pending_tx_info->req,
|
|
- pending_tx_info->extra_count, status);
|
|
+ _make_tx_response(queue, &pending_tx_info->req,
|
|
+ pending_tx_info->extra_count, status);
|
|
|
|
/* Release the pending index before pusing the Tx response so
|
|
* its available before a new Tx request is pushed by the
|
|
@@ -1424,32 +1465,19 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
|
|
spin_unlock_irqrestore(&queue->response_lock, flags);
|
|
}
|
|
|
|
-
|
|
static void make_tx_response(struct xenvif_queue *queue,
|
|
- struct xen_netif_tx_request *txp,
|
|
+ const struct xen_netif_tx_request *txp,
|
|
unsigned int extra_count,
|
|
- s8 st)
|
|
+ s8 status)
|
|
{
|
|
- RING_IDX i = queue->tx.rsp_prod_pvt;
|
|
- struct xen_netif_tx_response *resp;
|
|
-
|
|
- resp = RING_GET_RESPONSE(&queue->tx, i);
|
|
- resp->id = txp->id;
|
|
- resp->status = st;
|
|
-
|
|
- while (extra_count-- != 0)
|
|
- RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL;
|
|
+ unsigned long flags;
|
|
|
|
- queue->tx.rsp_prod_pvt = ++i;
|
|
-}
|
|
+ spin_lock_irqsave(&queue->response_lock, flags);
|
|
|
|
-static void push_tx_responses(struct xenvif_queue *queue)
|
|
-{
|
|
- int notify;
|
|
+ _make_tx_response(queue, txp, extra_count, status);
|
|
+ push_tx_responses(queue);
|
|
|
|
- RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
|
|
- if (notify)
|
|
- notify_remote_via_irq(queue->tx_irq);
|
|
+ spin_unlock_irqrestore(&queue->response_lock, flags);
|
|
}
|
|
|
|
static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
|
|
diff --git drivers/pci/host/pcie-mediatek.c drivers/pci/host/pcie-mediatek.c
|
|
index 60c3110b5151..6a47a6681f8d 100644
|
|
--- drivers/pci/host/pcie-mediatek.c
|
|
+++ drivers/pci/host/pcie-mediatek.c
|
|
@@ -628,6 +628,14 @@ static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
|
|
while ((status = readl(port->base + PCIE_INT_STATUS)) & MSI_STATUS) {
|
|
unsigned long imsi_status;
|
|
|
|
+ /*
|
|
+ * The interrupt status can be cleared even if the
|
|
+ * MSI status remains pending. As such, given the
|
|
+ * edge-triggered interrupt type, its status should
|
|
+ * be cleared before being dispatched to the
|
|
+ * handler of the underlying device.
|
|
+ */
|
|
+ writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
|
|
while ((imsi_status = readl(port->base + PCIE_IMSI_STATUS))) {
|
|
for_each_set_bit(bit, &imsi_status, MTK_MSI_IRQS_NUM) {
|
|
/* Clear the MSI */
|
|
@@ -636,8 +644,6 @@ static irqreturn_t mtk_pcie_intr_handler(int irq, void *data)
|
|
generic_handle_irq(virq);
|
|
}
|
|
}
|
|
- /* Clear MSI interrupt status */
|
|
- writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
|
|
}
|
|
}
|
|
|
|
diff --git drivers/pci/msi.c drivers/pci/msi.c
|
|
index bbddf492da9f..548045dda97c 100644
|
|
--- drivers/pci/msi.c
|
|
+++ drivers/pci/msi.c
|
|
@@ -1380,7 +1380,7 @@ irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
|
|
{
|
|
return (irq_hw_number_t)desc->msi_attrib.entry_nr |
|
|
PCI_DEVID(dev->bus->number, dev->devfn) << 11 |
|
|
- (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
|
|
+ ((irq_hw_number_t)(pci_domain_nr(dev->bus) & 0xFFFFFFFF)) << 27;
|
|
}
|
|
|
|
static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc)
|
|
diff --git drivers/pci/quirks.c drivers/pci/quirks.c
|
|
index e32147929cf3..ef9303547484 100644
|
|
--- drivers/pci/quirks.c
|
|
+++ drivers/pci/quirks.c
|
|
@@ -441,10 +441,13 @@ static void quirk_amd_dwc_class(struct pci_dev *pdev)
|
|
{
|
|
u32 class = pdev->class;
|
|
|
|
- /* Use "USB Device (not host controller)" class */
|
|
- pdev->class = PCI_CLASS_SERIAL_USB_DEVICE;
|
|
- dev_info(&pdev->dev, "PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
|
|
- class, pdev->class);
|
|
+ if (class != PCI_CLASS_SERIAL_USB_DEVICE) {
|
|
+ /* Use "USB Device (not host controller)" class */
|
|
+ pdev->class = PCI_CLASS_SERIAL_USB_DEVICE;
|
|
+ dev_info(&pdev->dev,
|
|
+ "PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
|
|
+ class, pdev->class);
|
|
+ }
|
|
}
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB,
|
|
quirk_amd_dwc_class);
|
|
@@ -3450,6 +3453,19 @@ static void quirk_no_pm_reset(struct pci_dev *dev)
|
|
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
|
|
PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset);
|
|
|
|
+/*
|
|
+ * Spectrum-{1,2,3,4} devices report that a D3hot->D0 transition causes a reset
|
|
+ * (i.e., they advertise NoSoftRst-). However, this transition does not have
|
|
+ * any effect on the device: It continues to be operational and network ports
|
|
+ * remain up. Advertising this support makes it seem as if a PM reset is viable
|
|
+ * for these devices. Mark it as unavailable to skip it when testing reset
|
|
+ * methods.
|
|
+ */
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, 0xcb84, quirk_no_pm_reset);
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, 0xcf6c, quirk_no_pm_reset);
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, 0xcf70, quirk_no_pm_reset);
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, 0xcf80, quirk_no_pm_reset);
|
|
+
|
|
/*
|
|
* Thunderbolt controllers with broken MSI hotplug signaling:
|
|
* Entire 1st generation (Light Ridge, Eagle Ridge, Light Peak) and part
|
|
diff --git drivers/phy/ti/phy-omap-usb2.c drivers/phy/ti/phy-omap-usb2.c
|
|
index fe909fd8144f..ae94e1e66bcc 100644
|
|
--- drivers/phy/ti/phy-omap-usb2.c
|
|
+++ drivers/phy/ti/phy-omap-usb2.c
|
|
@@ -64,7 +64,7 @@ static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
|
|
{
|
|
struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
|
|
|
|
- if (!phy->comparator)
|
|
+ if (!phy->comparator || !phy->comparator->set_vbus)
|
|
return -ENODEV;
|
|
|
|
return phy->comparator->set_vbus(phy->comparator, enabled);
|
|
@@ -74,7 +74,7 @@ static int omap_usb_start_srp(struct usb_otg *otg)
|
|
{
|
|
struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
|
|
|
|
- if (!phy->comparator)
|
|
+ if (!phy->comparator || !phy->comparator->start_srp)
|
|
return -ENODEV;
|
|
|
|
return phy->comparator->start_srp(phy->comparator);
|
|
diff --git drivers/pnp/pnpacpi/rsparser.c drivers/pnp/pnpacpi/rsparser.c
|
|
index 43d8ed577e70..d8cee80e8df8 100644
|
|
--- drivers/pnp/pnpacpi/rsparser.c
|
|
+++ drivers/pnp/pnpacpi/rsparser.c
|
|
@@ -160,13 +160,13 @@ static int vendor_resource_matches(struct pnp_dev *dev,
|
|
static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
|
|
struct acpi_resource_vendor_typed *vendor)
|
|
{
|
|
- if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
|
|
- u64 start, length;
|
|
+ struct { u64 start, length; } range;
|
|
|
|
- memcpy(&start, vendor->byte_data, sizeof(start));
|
|
- memcpy(&length, vendor->byte_data + 8, sizeof(length));
|
|
-
|
|
- pnp_add_mem_resource(dev, start, start + length - 1, 0);
|
|
+ if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid,
|
|
+ sizeof(range))) {
|
|
+ memcpy(&range, vendor->byte_data, sizeof(range));
|
|
+ pnp_add_mem_resource(dev, range.start, range.start +
|
|
+ range.length - 1, 0);
|
|
}
|
|
}
|
|
|
|
diff --git drivers/power/supply/bq27xxx_battery_i2c.c drivers/power/supply/bq27xxx_battery_i2c.c
|
|
index 426ce81333a5..3eb839405d3f 100644
|
|
--- drivers/power/supply/bq27xxx_battery_i2c.c
|
|
+++ drivers/power/supply/bq27xxx_battery_i2c.c
|
|
@@ -217,7 +217,9 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
|
|
{
|
|
struct bq27xxx_device_info *di = i2c_get_clientdata(client);
|
|
|
|
- free_irq(client->irq, di);
|
|
+ if (client->irq)
|
|
+ free_irq(client->irq, di);
|
|
+
|
|
bq27xxx_battery_teardown(di);
|
|
|
|
mutex_lock(&battery_mutex);
|
|
diff --git drivers/regulator/pwm-regulator.c drivers/regulator/pwm-regulator.c
|
|
index a2fd140eff81..5faa5906ad69 100644
|
|
--- drivers/regulator/pwm-regulator.c
|
|
+++ drivers/regulator/pwm-regulator.c
|
|
@@ -164,6 +164,9 @@ static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
|
|
pwm_get_state(drvdata->pwm, &pstate);
|
|
|
|
voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit);
|
|
+ if (voltage < min(max_uV_duty, min_uV_duty) ||
|
|
+ voltage > max(max_uV_duty, min_uV_duty))
|
|
+ return -ENOTRECOVERABLE;
|
|
|
|
/*
|
|
* The dutycycle for min_uV might be greater than the one for max_uV.
|
|
diff --git drivers/reset/hisilicon/hi6220_reset.c drivers/reset/hisilicon/hi6220_reset.c
|
|
index d5e5229308f2..d77a7ad7e57a 100644
|
|
--- drivers/reset/hisilicon/hi6220_reset.c
|
|
+++ drivers/reset/hisilicon/hi6220_reset.c
|
|
@@ -107,7 +107,7 @@ static int hi6220_reset_probe(struct platform_device *pdev)
|
|
if (!data)
|
|
return -ENOMEM;
|
|
|
|
- type = (enum hi6220_reset_ctrl_type)of_device_get_match_data(dev);
|
|
+ type = (uintptr_t)of_device_get_match_data(dev);
|
|
|
|
regmap = syscon_node_to_regmap(np);
|
|
if (IS_ERR(regmap)) {
|
|
diff --git drivers/rpmsg/virtio_rpmsg_bus.c drivers/rpmsg/virtio_rpmsg_bus.c
|
|
index 82b83002fcba..5aeb976fb4ee 100644
|
|
--- drivers/rpmsg/virtio_rpmsg_bus.c
|
|
+++ drivers/rpmsg/virtio_rpmsg_bus.c
|
|
@@ -389,6 +389,7 @@ static void virtio_rpmsg_release_device(struct device *dev)
|
|
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
|
|
struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
|
|
|
|
+ kfree(rpdev->driver_override);
|
|
kfree(vch);
|
|
}
|
|
|
|
diff --git drivers/s390/block/scm_blk.c drivers/s390/block/scm_blk.c
|
|
index 5c944ee76ec1..a37fd27258bd 100644
|
|
--- drivers/s390/block/scm_blk.c
|
|
+++ drivers/s390/block/scm_blk.c
|
|
@@ -17,6 +17,7 @@
|
|
#include <linux/genhd.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/list.h>
|
|
+#include <linux/io.h>
|
|
#include <asm/eadm.h>
|
|
#include "scm_blk.h"
|
|
|
|
@@ -130,7 +131,7 @@ static void scm_request_done(struct scm_request *scmrq)
|
|
|
|
for (i = 0; i < nr_requests_per_io && scmrq->request[i]; i++) {
|
|
msb = &scmrq->aob->msb[i];
|
|
- aidaw = msb->data_addr;
|
|
+ aidaw = (u64)phys_to_virt(msb->data_addr);
|
|
|
|
if ((msb->flags & MSB_FLAG_IDA) && aidaw &&
|
|
IS_ALIGNED(aidaw, PAGE_SIZE))
|
|
@@ -195,12 +196,12 @@ static int scm_request_prepare(struct scm_request *scmrq)
|
|
msb->scm_addr = scmdev->address + ((u64) blk_rq_pos(req) << 9);
|
|
msb->oc = (rq_data_dir(req) == READ) ? MSB_OC_READ : MSB_OC_WRITE;
|
|
msb->flags |= MSB_FLAG_IDA;
|
|
- msb->data_addr = (u64) aidaw;
|
|
+ msb->data_addr = (u64)virt_to_phys(aidaw);
|
|
|
|
rq_for_each_segment(bv, req, iter) {
|
|
WARN_ON(bv.bv_offset);
|
|
msb->blk_count += bv.bv_len >> 12;
|
|
- aidaw->data_addr = (u64) page_address(bv.bv_page);
|
|
+ aidaw->data_addr = virt_to_phys(page_address(bv.bv_page));
|
|
aidaw++;
|
|
}
|
|
|
|
diff --git drivers/s390/net/qeth_l3_main.c drivers/s390/net/qeth_l3_main.c
|
|
index 8bccfd686b73..7d9a64e2691a 100644
|
|
--- drivers/s390/net/qeth_l3_main.c
|
|
+++ drivers/s390/net/qeth_l3_main.c
|
|
@@ -364,9 +364,10 @@ static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover)
|
|
if (!recover) {
|
|
hash_del(&addr->hnode);
|
|
kfree(addr);
|
|
- continue;
|
|
+ } else {
|
|
+ /* prepare for recovery */
|
|
+ addr->disp_flag = QETH_DISP_ADDR_ADD;
|
|
}
|
|
- addr->disp_flag = QETH_DISP_ADDR_ADD;
|
|
}
|
|
|
|
spin_unlock_bh(&card->ip_lock);
|
|
@@ -404,11 +405,13 @@ static void qeth_l3_recover_ip(struct qeth_card *card)
|
|
} else
|
|
rc = qeth_l3_register_addr_entry(card, addr);
|
|
|
|
- if (!rc) {
|
|
+ if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) {
|
|
+ /* keep it in the records */
|
|
addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
|
|
if (addr->ref_counter < 1)
|
|
qeth_l3_delete_ip(card, addr);
|
|
} else {
|
|
+ /* bad address */
|
|
hash_del(&addr->hnode);
|
|
kfree(addr);
|
|
}
|
|
diff --git drivers/scsi/Kconfig drivers/scsi/Kconfig
|
|
index ba1bfb30a272..aeb73c170b3a 100644
|
|
--- drivers/scsi/Kconfig
|
|
+++ drivers/scsi/Kconfig
|
|
@@ -1394,7 +1394,7 @@ source "drivers/scsi/arm/Kconfig"
|
|
|
|
config JAZZ_ESP
|
|
bool "MIPS JAZZ FAS216 SCSI support"
|
|
- depends on MACH_JAZZ && SCSI
|
|
+ depends on MACH_JAZZ && SCSI=y
|
|
select SCSI_SPI_ATTRS
|
|
help
|
|
This is the driver for the onboard SCSI host adapter of MIPS Magnum
|
|
diff --git drivers/scsi/fcoe/fcoe_ctlr.c drivers/scsi/fcoe/fcoe_ctlr.c
|
|
index 57826f7bb9f2..1c8fa41aa3ab 100644
|
|
--- drivers/scsi/fcoe/fcoe_ctlr.c
|
|
+++ drivers/scsi/fcoe/fcoe_ctlr.c
|
|
@@ -330,17 +330,16 @@ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
|
|
{
|
|
struct fcoe_fcf *sel;
|
|
struct fcoe_fcf *fcf;
|
|
- unsigned long flags;
|
|
|
|
mutex_lock(&fip->ctlr_mutex);
|
|
- spin_lock_irqsave(&fip->ctlr_lock, flags);
|
|
+ spin_lock_bh(&fip->ctlr_lock);
|
|
|
|
kfree_skb(fip->flogi_req);
|
|
fip->flogi_req = NULL;
|
|
list_for_each_entry(fcf, &fip->fcfs, list)
|
|
fcf->flogi_sent = 0;
|
|
|
|
- spin_unlock_irqrestore(&fip->ctlr_lock, flags);
|
|
+ spin_unlock_bh(&fip->ctlr_lock);
|
|
sel = fip->sel_fcf;
|
|
|
|
if (sel && ether_addr_equal(sel->fcf_mac, fip->dest_addr))
|
|
@@ -710,7 +709,6 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
|
|
{
|
|
struct fc_frame *fp;
|
|
struct fc_frame_header *fh;
|
|
- unsigned long flags;
|
|
u16 old_xid;
|
|
u8 op;
|
|
u8 mac[ETH_ALEN];
|
|
@@ -744,11 +742,11 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
|
|
op = FIP_DT_FLOGI;
|
|
if (fip->mode == FIP_MODE_VN2VN)
|
|
break;
|
|
- spin_lock_irqsave(&fip->ctlr_lock, flags);
|
|
+ spin_lock_bh(&fip->ctlr_lock);
|
|
kfree_skb(fip->flogi_req);
|
|
fip->flogi_req = skb;
|
|
fip->flogi_req_send = 1;
|
|
- spin_unlock_irqrestore(&fip->ctlr_lock, flags);
|
|
+ spin_unlock_bh(&fip->ctlr_lock);
|
|
schedule_work(&fip->timer_work);
|
|
return -EINPROGRESS;
|
|
case ELS_FDISC:
|
|
@@ -1725,11 +1723,10 @@ static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
|
|
static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
|
|
{
|
|
struct fcoe_fcf *fcf;
|
|
- unsigned long flags;
|
|
int error;
|
|
|
|
mutex_lock(&fip->ctlr_mutex);
|
|
- spin_lock_irqsave(&fip->ctlr_lock, flags);
|
|
+ spin_lock_bh(&fip->ctlr_lock);
|
|
LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
|
|
fcf = fcoe_ctlr_select(fip);
|
|
if (!fcf || fcf->flogi_sent) {
|
|
@@ -1740,7 +1737,7 @@ static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
|
|
fcoe_ctlr_solicit(fip, NULL);
|
|
error = fcoe_ctlr_flogi_send_locked(fip);
|
|
}
|
|
- spin_unlock_irqrestore(&fip->ctlr_lock, flags);
|
|
+ spin_unlock_bh(&fip->ctlr_lock);
|
|
mutex_unlock(&fip->ctlr_mutex);
|
|
return error;
|
|
}
|
|
@@ -1757,9 +1754,8 @@ static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
|
|
static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
|
|
{
|
|
struct fcoe_fcf *fcf;
|
|
- unsigned long flags;
|
|
|
|
- spin_lock_irqsave(&fip->ctlr_lock, flags);
|
|
+ spin_lock_bh(&fip->ctlr_lock);
|
|
fcf = fip->sel_fcf;
|
|
if (!fcf || !fip->flogi_req_send)
|
|
goto unlock;
|
|
@@ -1786,7 +1782,7 @@ static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
|
|
} else /* XXX */
|
|
LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
|
|
unlock:
|
|
- spin_unlock_irqrestore(&fip->ctlr_lock, flags);
|
|
+ spin_unlock_bh(&fip->ctlr_lock);
|
|
}
|
|
|
|
/**
|
|
diff --git drivers/scsi/isci/request.c drivers/scsi/isci/request.c
|
|
index 2f151708b59a..13ecf554762e 100644
|
|
--- drivers/scsi/isci/request.c
|
|
+++ drivers/scsi/isci/request.c
|
|
@@ -3398,7 +3398,7 @@ static enum sci_status isci_io_request_build(struct isci_host *ihost,
|
|
return SCI_FAILURE;
|
|
}
|
|
|
|
- return SCI_SUCCESS;
|
|
+ return status;
|
|
}
|
|
|
|
static struct isci_request *isci_request_from_tag(struct isci_host *ihost, u16 tag)
|
|
diff --git drivers/scsi/libfc/fc_fcp.c drivers/scsi/libfc/fc_fcp.c
|
|
index 772c35a5c49e..72ceffc58112 100644
|
|
--- drivers/scsi/libfc/fc_fcp.c
|
|
+++ drivers/scsi/libfc/fc_fcp.c
|
|
@@ -283,6 +283,11 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
|
|
if (!fsp->seq_ptr)
|
|
return -EINVAL;
|
|
|
|
+ if (fsp->state & FC_SRB_ABORT_PENDING) {
|
|
+ FC_FCP_DBG(fsp, "abort already pending\n");
|
|
+ return -EBUSY;
|
|
+ }
|
|
+
|
|
per_cpu_ptr(fsp->lp->stats, get_cpu())->FcpPktAborts++;
|
|
put_cpu();
|
|
|
|
@@ -1693,7 +1698,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
|
|
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
|
|
fc_fcp_rec(fsp);
|
|
else
|
|
- fc_fcp_recovery(fsp, FC_ERROR);
|
|
+ fc_fcp_recovery(fsp, FC_TIMED_OUT);
|
|
break;
|
|
}
|
|
fc_fcp_unlock_pkt(fsp);
|
|
@@ -1711,11 +1716,12 @@ static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code)
|
|
fsp->status_code = code;
|
|
fsp->cdb_status = 0;
|
|
fsp->io_status = 0;
|
|
- /*
|
|
- * if this fails then we let the scsi command timer fire and
|
|
- * scsi-ml escalate.
|
|
- */
|
|
- fc_fcp_send_abort(fsp);
|
|
+ if (!fsp->cmd)
|
|
+ /*
|
|
+ * Only abort non-scsi commands; otherwise let the
|
|
+ * scsi command timer fire and scsi-ml escalate.
|
|
+ */
|
|
+ fc_fcp_send_abort(fsp);
|
|
}
|
|
|
|
/**
|
|
diff --git drivers/scsi/lpfc/lpfc.h drivers/scsi/lpfc/lpfc.h
|
|
index 5fc41aa53ceb..97a2f6c6337c 100644
|
|
--- drivers/scsi/lpfc/lpfc.h
|
|
+++ drivers/scsi/lpfc/lpfc.h
|
|
@@ -31,6 +31,7 @@
|
|
struct lpfc_sli2_slim;
|
|
|
|
#define ELX_MODEL_NAME_SIZE 80
|
|
+#define ELX_FW_NAME_SIZE 84
|
|
|
|
#define LPFC_PCI_DEV_LP 0x1
|
|
#define LPFC_PCI_DEV_OC 0x2
|
|
diff --git drivers/scsi/lpfc/lpfc_init.c drivers/scsi/lpfc/lpfc_init.c
|
|
index 3e9574eede20..0f954853ccad 100644
|
|
--- drivers/scsi/lpfc/lpfc_init.c
|
|
+++ drivers/scsi/lpfc/lpfc_init.c
|
|
@@ -11086,7 +11086,7 @@ out:
|
|
int
|
|
lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
|
|
{
|
|
- uint8_t file_name[ELX_MODEL_NAME_SIZE];
|
|
+ char file_name[ELX_FW_NAME_SIZE] = {0};
|
|
int ret;
|
|
const struct firmware *fw;
|
|
|
|
@@ -11095,7 +11095,7 @@ lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
|
|
LPFC_SLI_INTF_IF_TYPE_2)
|
|
return -EPERM;
|
|
|
|
- snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp", phba->ModelName);
|
|
+ scnprintf(file_name, sizeof(file_name), "%s.grp", phba->ModelName);
|
|
|
|
if (fw_upgrade == INT_FW_UPGRADE) {
|
|
ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
|
|
diff --git drivers/spi/spi-ppc4xx.c drivers/spi/spi-ppc4xx.c
|
|
index 967d94844b30..58765a62fc15 100644
|
|
--- drivers/spi/spi-ppc4xx.c
|
|
+++ drivers/spi/spi-ppc4xx.c
|
|
@@ -173,10 +173,8 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
|
|
int scr;
|
|
u8 cdm = 0;
|
|
u32 speed;
|
|
- u8 bits_per_word;
|
|
|
|
/* Start with the generic configuration for this device. */
|
|
- bits_per_word = spi->bits_per_word;
|
|
speed = spi->max_speed_hz;
|
|
|
|
/*
|
|
@@ -184,9 +182,6 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
|
|
* the transfer to overwrite the generic configuration with zeros.
|
|
*/
|
|
if (t) {
|
|
- if (t->bits_per_word)
|
|
- bits_per_word = t->bits_per_word;
|
|
-
|
|
if (t->speed_hz)
|
|
speed = min(t->speed_hz, spi->max_speed_hz);
|
|
}
|
|
diff --git drivers/staging/iio/impedance-analyzer/ad5933.c drivers/staging/iio/impedance-analyzer/ad5933.c
|
|
index 6d31001d1825..344053df0383 100644
|
|
--- drivers/staging/iio/impedance-analyzer/ad5933.c
|
|
+++ drivers/staging/iio/impedance-analyzer/ad5933.c
|
|
@@ -658,7 +658,7 @@ static void ad5933_work(struct work_struct *work)
|
|
struct ad5933_state, work.work);
|
|
struct iio_dev *indio_dev = i2c_get_clientdata(st->client);
|
|
__be16 buf[2];
|
|
- int val[2];
|
|
+ u16 val[2];
|
|
unsigned char status;
|
|
int ret;
|
|
|
|
diff --git drivers/target/target_core_device.c drivers/target/target_core_device.c
|
|
index 907b06056f02..ccefa4eb9f1f 100644
|
|
--- drivers/target/target_core_device.c
|
|
+++ drivers/target/target_core_device.c
|
|
@@ -164,7 +164,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
|
|
struct se_session *se_sess = se_cmd->se_sess;
|
|
struct se_node_acl *nacl = se_sess->se_node_acl;
|
|
struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
|
|
- unsigned long flags;
|
|
|
|
rcu_read_lock();
|
|
deve = target_nacl_find_deve(nacl, unpacked_lun);
|
|
@@ -195,10 +194,6 @@ out_unlock:
|
|
se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
|
|
se_tmr->tmr_dev = rcu_dereference_raw(se_lun->lun_se_dev);
|
|
|
|
- spin_lock_irqsave(&se_tmr->tmr_dev->se_tmr_lock, flags);
|
|
- list_add_tail(&se_tmr->tmr_list, &se_tmr->tmr_dev->dev_tmr_list);
|
|
- spin_unlock_irqrestore(&se_tmr->tmr_dev->se_tmr_lock, flags);
|
|
-
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(transport_lookup_tmr_lun);
|
|
diff --git drivers/target/target_core_transport.c drivers/target/target_core_transport.c
|
|
index c20997bf314e..41ebdd629b9d 100644
|
|
--- drivers/target/target_core_transport.c
|
|
+++ drivers/target/target_core_transport.c
|
|
@@ -3424,6 +3424,10 @@ int transport_generic_handle_tmr(
|
|
unsigned long flags;
|
|
bool aborted = false;
|
|
|
|
+ spin_lock_irqsave(&cmd->se_dev->se_tmr_lock, flags);
|
|
+ list_add_tail(&cmd->se_tmr_req->tmr_list, &cmd->se_dev->dev_tmr_list);
|
|
+ spin_unlock_irqrestore(&cmd->se_dev->se_tmr_lock, flags);
|
|
+
|
|
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
|
if (cmd->transport_state & CMD_T_ABORTED) {
|
|
aborted = true;
|
|
diff --git drivers/tty/serial/imx.c drivers/tty/serial/imx.c
|
|
index 7fccf69931c5..6cfa6a908336 100644
|
|
--- drivers/tty/serial/imx.c
|
|
+++ drivers/tty/serial/imx.c
|
|
@@ -2215,7 +2215,7 @@ static int serial_imx_probe(struct platform_device *pdev)
|
|
/* For register access, we only need to enable the ipg clock. */
|
|
ret = clk_prepare_enable(sport->clk_ipg);
|
|
if (ret) {
|
|
- dev_err(&pdev->dev, "failed to enable per clk: %d\n", ret);
|
|
+ dev_err(&pdev->dev, "failed to enable ipg clk: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
diff --git drivers/tty/serial/sc16is7xx.c drivers/tty/serial/sc16is7xx.c
|
|
index 73280d400eb2..3afaab69f0e2 100644
|
|
--- drivers/tty/serial/sc16is7xx.c
|
|
+++ drivers/tty/serial/sc16is7xx.c
|
|
@@ -29,6 +29,7 @@
|
|
#include <linux/tty_flip.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/uaccess.h>
|
|
+#include <linux/units.h>
|
|
#include <uapi/linux/sched/types.h>
|
|
|
|
#define SC16IS7XX_NAME "sc16is7xx"
|
|
@@ -1401,9 +1402,12 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)
|
|
|
|
/* Setup SPI bus */
|
|
spi->bits_per_word = 8;
|
|
- /* only supports mode 0 on SC16IS762 */
|
|
+ /* For all variants, only mode 0 is supported */
|
|
+ if ((spi->mode & SPI_MODE_X_MASK) != SPI_MODE_0)
|
|
+ return dev_err_probe(&spi->dev, -EINVAL, "Unsupported SPI mode\n");
|
|
+
|
|
spi->mode = spi->mode ? : SPI_MODE_0;
|
|
- spi->max_speed_hz = spi->max_speed_hz ? : 15000000;
|
|
+ spi->max_speed_hz = spi->max_speed_hz ? : 4 * HZ_PER_MHZ;
|
|
ret = spi_setup(spi);
|
|
if (ret)
|
|
return ret;
|
|
diff --git drivers/uio/uio.c drivers/uio/uio.c
|
|
index be33a5ce3d8e..3ebea6388220 100644
|
|
--- drivers/uio/uio.c
|
|
+++ drivers/uio/uio.c
|
|
@@ -465,13 +465,13 @@ static int uio_open(struct inode *inode, struct file *filep)
|
|
|
|
mutex_lock(&minor_lock);
|
|
idev = idr_find(&uio_idr, iminor(inode));
|
|
- mutex_unlock(&minor_lock);
|
|
if (!idev) {
|
|
ret = -ENODEV;
|
|
+ mutex_unlock(&minor_lock);
|
|
goto out;
|
|
}
|
|
-
|
|
get_device(&idev->dev);
|
|
+ mutex_unlock(&minor_lock);
|
|
|
|
if (!try_module_get(idev->owner)) {
|
|
ret = -ENODEV;
|
|
@@ -1020,9 +1020,8 @@ void uio_unregister_device(struct uio_info *info)
|
|
idev->info = NULL;
|
|
mutex_unlock(&idev->info_lock);
|
|
|
|
- device_unregister(&idev->dev);
|
|
-
|
|
uio_free_minor(minor);
|
|
+ device_unregister(&idev->dev);
|
|
|
|
return;
|
|
}
|
|
diff --git drivers/usb/chipidea/core.c drivers/usb/chipidea/core.c
|
|
index 4cacb91c4729..a4880b137f1b 100644
|
|
--- drivers/usb/chipidea/core.c
|
|
+++ drivers/usb/chipidea/core.c
|
|
@@ -542,6 +542,13 @@ static irqreturn_t ci_irq_handler(int irq, void *data)
|
|
u32 otgsc = 0;
|
|
|
|
if (ci->in_lpm) {
|
|
+ /*
|
|
+ * If we already have a wakeup irq pending there,
|
|
+ * let's just return to wait resume finished firstly.
|
|
+ */
|
|
+ if (ci->wakeup_int)
|
|
+ return IRQ_HANDLED;
|
|
+
|
|
disable_irq_nosync(irq);
|
|
ci->wakeup_int = true;
|
|
pm_runtime_get(ci->dev);
|
|
diff --git drivers/usb/core/hub.c drivers/usb/core/hub.c
|
|
index 4a0765bca8e7..afe3a46a0d2d 100644
|
|
--- drivers/usb/core/hub.c
|
|
+++ drivers/usb/core/hub.c
|
|
@@ -43,8 +43,8 @@
|
|
#define USB_VENDOR_TEXAS_INSTRUMENTS 0x0451
|
|
#define USB_PRODUCT_TUSB8041_USB3 0x8140
|
|
#define USB_PRODUCT_TUSB8041_USB2 0x8142
|
|
-#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
|
|
-#define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02
|
|
+#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND BIT(0)
|
|
+#define HUB_QUIRK_DISABLE_AUTOSUSPEND BIT(1)
|
|
|
|
/* Protect struct usb_device->state and ->children members
|
|
* Note: Both are also protected by ->dev.sem, except that ->state can
|
|
@@ -2308,17 +2308,25 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
|
|
}
|
|
} else if (desc->bLength == sizeof
|
|
(struct usb_otg_descriptor)) {
|
|
- /* Set a_alt_hnp_support for legacy otg device */
|
|
- err = usb_control_msg(udev,
|
|
- usb_sndctrlpipe(udev, 0),
|
|
- USB_REQ_SET_FEATURE, 0,
|
|
- USB_DEVICE_A_ALT_HNP_SUPPORT,
|
|
- 0, NULL, 0,
|
|
- USB_CTRL_SET_TIMEOUT);
|
|
- if (err < 0)
|
|
- dev_err(&udev->dev,
|
|
- "set a_alt_hnp_support failed: %d\n",
|
|
- err);
|
|
+ /*
|
|
+ * We are operating on a legacy OTP device
|
|
+ * These should be told that they are operating
|
|
+ * on the wrong port if we have another port that does
|
|
+ * support HNP
|
|
+ */
|
|
+ if (bus->otg_port != 0) {
|
|
+ /* Set a_alt_hnp_support for legacy otg device */
|
|
+ err = usb_control_msg(udev,
|
|
+ usb_sndctrlpipe(udev, 0),
|
|
+ USB_REQ_SET_FEATURE, 0,
|
|
+ USB_DEVICE_A_ALT_HNP_SUPPORT,
|
|
+ 0, NULL, 0,
|
|
+ USB_CTRL_SET_TIMEOUT);
|
|
+ if (err < 0)
|
|
+ dev_err(&udev->dev,
|
|
+ "set a_alt_hnp_support failed: %d\n",
|
|
+ err);
|
|
+ }
|
|
}
|
|
}
|
|
#endif
|
|
diff --git drivers/usb/dwc3/ep0.c drivers/usb/dwc3/ep0.c
|
|
index 17bc5b958ea0..f3f9fca246b8 100644
|
|
--- drivers/usb/dwc3/ep0.c
|
|
+++ drivers/usb/dwc3/ep0.c
|
|
@@ -246,7 +246,10 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
|
|
struct dwc3_request *req;
|
|
|
|
req = next_request(&dep->pending_list);
|
|
- dwc3_gadget_giveback(dep, req, -ECONNRESET);
|
|
+ if (!dwc->connected)
|
|
+ dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
|
|
+ else
|
|
+ dwc3_gadget_giveback(dep, req, -ECONNRESET);
|
|
}
|
|
|
|
dwc->ep0state = EP0_SETUP_PHASE;
|
|
diff --git drivers/usb/gadget/function/f_mass_storage.c drivers/usb/gadget/function/f_mass_storage.c
|
|
index 6aee3cf50c74..43bceee1d6c7 100644
|
|
--- drivers/usb/gadget/function/f_mass_storage.c
|
|
+++ drivers/usb/gadget/function/f_mass_storage.c
|
|
@@ -576,21 +576,37 @@ static int start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
|
|
|
|
static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
|
|
{
|
|
+ int rc;
|
|
+
|
|
if (!fsg_is_set(common))
|
|
return false;
|
|
bh->state = BUF_STATE_SENDING;
|
|
- if (start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq))
|
|
+ rc = start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq);
|
|
+ if (rc) {
|
|
bh->state = BUF_STATE_EMPTY;
|
|
+ if (rc == -ESHUTDOWN) {
|
|
+ common->running = 0;
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
return true;
|
|
}
|
|
|
|
static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
|
|
{
|
|
+ int rc;
|
|
+
|
|
if (!fsg_is_set(common))
|
|
return false;
|
|
bh->state = BUF_STATE_RECEIVING;
|
|
- if (start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq))
|
|
+ rc = start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq);
|
|
+ if (rc) {
|
|
bh->state = BUF_STATE_FULL;
|
|
+ if (rc == -ESHUTDOWN) {
|
|
+ common->running = 0;
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
return true;
|
|
}
|
|
|
|
diff --git drivers/usb/gadget/function/f_ncm.c drivers/usb/gadget/function/f_ncm.c
|
|
index 47d1f4e960cb..9a75e4c49976 100644
|
|
--- drivers/usb/gadget/function/f_ncm.c
|
|
+++ drivers/usb/gadget/function/f_ncm.c
|
|
@@ -1370,7 +1370,15 @@ parse_ntb:
|
|
"Parsed NTB with %d frames\n", dgram_counter);
|
|
|
|
to_process -= block_len;
|
|
- if (to_process != 0) {
|
|
+
|
|
+ /*
|
|
+ * Windows NCM driver avoids USB ZLPs by adding a 1-byte
|
|
+ * zero pad as needed.
|
|
+ */
|
|
+ if (to_process == 1 &&
|
|
+ (*(unsigned char *)(ntb_ptr + block_len) == 0x00)) {
|
|
+ to_process--;
|
|
+ } else if (to_process > 0) {
|
|
ntb_ptr = (unsigned char *)(ntb_ptr + block_len);
|
|
goto parse_ntb;
|
|
}
|
|
diff --git drivers/usb/mon/mon_bin.c drivers/usb/mon/mon_bin.c
|
|
index a6da9b72f46b..21b184d2170a 100644
|
|
--- drivers/usb/mon/mon_bin.c
|
|
+++ drivers/usb/mon/mon_bin.c
|
|
@@ -1246,14 +1246,19 @@ static int mon_bin_vma_fault(struct vm_fault *vmf)
|
|
struct mon_reader_bin *rp = vmf->vma->vm_private_data;
|
|
unsigned long offset, chunk_idx;
|
|
struct page *pageptr;
|
|
+ unsigned long flags;
|
|
|
|
+ spin_lock_irqsave(&rp->b_lock, flags);
|
|
offset = vmf->pgoff << PAGE_SHIFT;
|
|
- if (offset >= rp->b_size)
|
|
+ if (offset >= rp->b_size) {
|
|
+ spin_unlock_irqrestore(&rp->b_lock, flags);
|
|
return VM_FAULT_SIGBUS;
|
|
+ }
|
|
chunk_idx = offset / CHUNK_SIZE;
|
|
pageptr = rp->b_vec[chunk_idx].pg;
|
|
get_page(pageptr);
|
|
vmf->page = pageptr;
|
|
+ spin_unlock_irqrestore(&rp->b_lock, flags);
|
|
return 0;
|
|
}
|
|
|
|
diff --git drivers/usb/phy/phy-mxs-usb.c drivers/usb/phy/phy-mxs-usb.c
|
|
index 6e462a8d8309..bbfdd926bc70 100644
|
|
--- drivers/usb/phy/phy-mxs-usb.c
|
|
+++ drivers/usb/phy/phy-mxs-usb.c
|
|
@@ -303,8 +303,7 @@ static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
|
|
|
|
static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy)
|
|
{
|
|
- return IS_ENABLED(CONFIG_USB_OTG) &&
|
|
- mxs_phy->phy.last_event == USB_EVENT_ID;
|
|
+ return mxs_phy->phy.last_event == USB_EVENT_ID;
|
|
}
|
|
|
|
static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
|
|
diff --git drivers/usb/serial/cp210x.c drivers/usb/serial/cp210x.c
|
|
index df524ce8c050..4158432fc16f 100644
|
|
--- drivers/usb/serial/cp210x.c
|
|
+++ drivers/usb/serial/cp210x.c
|
|
@@ -150,6 +150,7 @@ static const struct usb_device_id id_table[] = {
|
|
{ USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
|
|
{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
|
|
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
|
|
+ { USB_DEVICE(0x10C4, 0x87ED) }, /* IMST USB-Stick for Smart Meter */
|
|
{ USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */
|
|
{ USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */
|
|
{ USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
|
|
diff --git drivers/usb/serial/option.c drivers/usb/serial/option.c
|
|
index 902bbe52a1d6..8744d91de155 100644
|
|
--- drivers/usb/serial/option.c
|
|
+++ drivers/usb/serial/option.c
|
|
@@ -2271,6 +2271,7 @@ static const struct usb_device_id option_ids[] = {
|
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */
|
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
|
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
|
|
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
|
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */
|
|
.driver_info = RSVD(4) },
|
|
{ USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
|
|
diff --git drivers/usb/serial/qcserial.c drivers/usb/serial/qcserial.c
|
|
index 6ea6cbbebfba..03dc86977e6d 100644
|
|
--- drivers/usb/serial/qcserial.c
|
|
+++ drivers/usb/serial/qcserial.c
|
|
@@ -188,6 +188,8 @@ static const struct usb_device_id id_table[] = {
|
|
{DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */
|
|
{DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */
|
|
{DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */
|
|
+ {DEVICE_SWI(0x413c, 0x8217)}, /* Dell Wireless DW5826e */
|
|
+ {DEVICE_SWI(0x413c, 0x8218)}, /* Dell Wireless DW5826e QDL */
|
|
|
|
/* Huawei devices */
|
|
{DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
|
|
diff --git drivers/vhost/vhost.c drivers/vhost/vhost.c
|
|
index 93cdeb516594..03eb2941ff6c 100644
|
|
--- drivers/vhost/vhost.c
|
|
+++ drivers/vhost/vhost.c
|
|
@@ -2483,12 +2483,11 @@ EXPORT_SYMBOL_GPL(vhost_disable_notify);
|
|
/* Create a new message. */
|
|
struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type)
|
|
{
|
|
- struct vhost_msg_node *node = kmalloc(sizeof *node, GFP_KERNEL);
|
|
+ /* Make sure all padding within the structure is initialized. */
|
|
+ struct vhost_msg_node *node = kzalloc(sizeof(*node), GFP_KERNEL);
|
|
if (!node)
|
|
return NULL;
|
|
|
|
- /* Make sure all padding within the structure is initialized. */
|
|
- memset(&node->msg, 0, sizeof node->msg);
|
|
node->vq = vq;
|
|
node->msg.type = type;
|
|
return node;
|
|
diff --git drivers/video/fbdev/core/fb_defio.c drivers/video/fbdev/core/fb_defio.c
|
|
index 487d5e336e1b..36972138340d 100644
|
|
--- drivers/video/fbdev/core/fb_defio.c
|
|
+++ drivers/video/fbdev/core/fb_defio.c
|
|
@@ -78,11 +78,7 @@ int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasy
|
|
return 0;
|
|
|
|
inode_lock(inode);
|
|
- /* Kill off the delayed work */
|
|
- cancel_delayed_work_sync(&info->deferred_work);
|
|
-
|
|
- /* Run it immediately */
|
|
- schedule_delayed_work(&info->deferred_work, 0);
|
|
+ flush_delayed_work(&info->deferred_work);
|
|
inode_unlock(inode);
|
|
|
|
return 0;
|
|
diff --git drivers/video/fbdev/savage/savagefb_driver.c drivers/video/fbdev/savage/savagefb_driver.c
|
|
index c20468362f11..a4f15b9de2b6 100644
|
|
--- drivers/video/fbdev/savage/savagefb_driver.c
|
|
+++ drivers/video/fbdev/savage/savagefb_driver.c
|
|
@@ -869,6 +869,9 @@ static int savagefb_check_var(struct fb_var_screeninfo *var,
|
|
|
|
DBG("savagefb_check_var");
|
|
|
|
+ if (!var->pixclock)
|
|
+ return -EINVAL;
|
|
+
|
|
var->transp.offset = 0;
|
|
var->transp.length = 0;
|
|
switch (var->bits_per_pixel) {
|
|
diff --git drivers/video/fbdev/sis/sis_main.c drivers/video/fbdev/sis/sis_main.c
|
|
index e92303823a4b..9575a481eeaf 100644
|
|
--- drivers/video/fbdev/sis/sis_main.c
|
|
+++ drivers/video/fbdev/sis/sis_main.c
|
|
@@ -1437,6 +1437,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
|
|
|
vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
|
|
|
|
+ if (!var->pixclock)
|
|
+ return -EINVAL;
|
|
pixclock = var->pixclock;
|
|
|
|
if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
|
|
diff --git drivers/watchdog/bcm2835_wdt.c drivers/watchdog/bcm2835_wdt.c
|
|
index adb699145a07..4e653e71e232 100644
|
|
--- drivers/watchdog/bcm2835_wdt.c
|
|
+++ drivers/watchdog/bcm2835_wdt.c
|
|
@@ -44,6 +44,7 @@
|
|
|
|
#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
|
|
#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
|
|
+#define WDOG_TICKS_TO_MSECS(x) ((x) * 1000 >> 16)
|
|
|
|
struct bcm2835_wdt {
|
|
void __iomem *base;
|
|
@@ -140,7 +141,7 @@ static struct watchdog_device bcm2835_wdt_wdd = {
|
|
.info = &bcm2835_wdt_info,
|
|
.ops = &bcm2835_wdt_ops,
|
|
.min_timeout = 1,
|
|
- .max_timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET),
|
|
+ .max_hw_heartbeat_ms = WDOG_TICKS_TO_MSECS(PM_WDOG_TIME_SET),
|
|
.timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET),
|
|
};
|
|
|
|
diff --git drivers/watchdog/watchdog_dev.c drivers/watchdog/watchdog_dev.c
|
|
index 337ca3690d62..d26fb9016a9f 100644
|
|
--- drivers/watchdog/watchdog_dev.c
|
|
+++ drivers/watchdog/watchdog_dev.c
|
|
@@ -956,6 +956,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
|
|
|
|
/* Fill in the data structures */
|
|
cdev_init(&wd_data->cdev, &watchdog_fops);
|
|
+ wd_data->cdev.owner = wdd->ops->owner;
|
|
|
|
/* Add the device */
|
|
err = cdev_device_add(&wd_data->cdev, &wd_data->dev);
|
|
@@ -970,8 +971,6 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
|
|
return err;
|
|
}
|
|
|
|
- wd_data->cdev.owner = wdd->ops->owner;
|
|
-
|
|
/* Record time of most recent heartbeat as 'just before now'. */
|
|
wd_data->last_hw_keepalive = jiffies - 1;
|
|
|
|
diff --git fs/aio.c fs/aio.c
|
|
index 2eb3dba5ed16..816f1443626b 100644
|
|
--- fs/aio.c
|
|
+++ fs/aio.c
|
|
@@ -562,6 +562,13 @@ void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
|
|
struct kioctx *ctx = req->ki_ctx;
|
|
unsigned long flags;
|
|
|
|
+ /*
|
|
+ * kiocb didn't come from aio or is neither a read nor a write, hence
|
|
+ * ignore it.
|
|
+ */
|
|
+ if (!(iocb->ki_flags & IOCB_AIO_RW))
|
|
+ return;
|
|
+
|
|
spin_lock_irqsave(&ctx->ctx_lock, flags);
|
|
|
|
if (!req->ki_list.next)
|
|
@@ -1601,7 +1608,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
|
|
}
|
|
req->common.ki_pos = iocb->aio_offset;
|
|
req->common.ki_complete = aio_complete;
|
|
- req->common.ki_flags = iocb_flags(req->common.ki_filp);
|
|
+ req->common.ki_flags = iocb_flags(req->common.ki_filp) | IOCB_AIO_RW;
|
|
req->common.ki_hint = file_write_hint(file);
|
|
|
|
if (iocb->aio_flags & IOCB_FLAG_RESFD) {
|
|
diff --git fs/btrfs/dev-replace.c fs/btrfs/dev-replace.c
|
|
index f1e9dd246ab0..3238bd9c0d39 100644
|
|
--- fs/btrfs/dev-replace.c
|
|
+++ fs/btrfs/dev-replace.c
|
|
@@ -426,6 +426,23 @@ leave:
|
|
return ret;
|
|
}
|
|
|
|
+static int btrfs_check_replace_dev_names(struct btrfs_ioctl_dev_replace_args *args)
|
|
+{
|
|
+ if (args->start.srcdevid == 0) {
|
|
+ if (memchr(args->start.srcdev_name, 0,
|
|
+ sizeof(args->start.srcdev_name)) == NULL)
|
|
+ return -ENAMETOOLONG;
|
|
+ } else {
|
|
+ args->start.srcdev_name[0] = 0;
|
|
+ }
|
|
+
|
|
+ if (memchr(args->start.tgtdev_name, 0,
|
|
+ sizeof(args->start.tgtdev_name)) == NULL)
|
|
+ return -ENAMETOOLONG;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info,
|
|
struct btrfs_ioctl_dev_replace_args *args)
|
|
{
|
|
@@ -438,10 +455,9 @@ int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info,
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
-
|
|
- if ((args->start.srcdevid == 0 && args->start.srcdev_name[0] == '\0') ||
|
|
- args->start.tgtdev_name[0] == '\0')
|
|
- return -EINVAL;
|
|
+ ret = btrfs_check_replace_dev_names(args);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
ret = btrfs_dev_replace_start(fs_info, args->start.tgtdev_name,
|
|
args->start.srcdevid,
|
|
diff --git fs/btrfs/extent-tree.c fs/btrfs/extent-tree.c
|
|
index deb01e59da02..6741710a149e 100644
|
|
--- fs/btrfs/extent-tree.c
|
|
+++ fs/btrfs/extent-tree.c
|
|
@@ -2070,7 +2070,8 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
|
|
u64 bytes_left, end;
|
|
u64 aligned_start = ALIGN(start, 1 << 9);
|
|
|
|
- if (WARN_ON(start != aligned_start)) {
|
|
+ /* Adjust the range to be aligned to 512B sectors if necessary. */
|
|
+ if (start != aligned_start) {
|
|
len -= aligned_start - start;
|
|
len = round_down(len, 1 << 9);
|
|
start = aligned_start;
|
|
diff --git fs/btrfs/ioctl.c fs/btrfs/ioctl.c
|
|
index 93b83dc298ac..c8bc8cf5a41f 100644
|
|
--- fs/btrfs/ioctl.c
|
|
+++ fs/btrfs/ioctl.c
|
|
@@ -2668,6 +2668,10 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
|
|
kfree(range);
|
|
goto out;
|
|
}
|
|
+ if (range->flags & ~BTRFS_DEFRAG_RANGE_FLAGS_SUPP) {
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto out;
|
|
+ }
|
|
/* compression requires us to start the IO */
|
|
if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) {
|
|
range->flags |= BTRFS_DEFRAG_RANGE_START_IO;
|
|
diff --git fs/btrfs/send.c fs/btrfs/send.c
|
|
index f2cb7fec7547..fa9797f8501e 100644
|
|
--- fs/btrfs/send.c
|
|
+++ fs/btrfs/send.c
|
|
@@ -6662,7 +6662,7 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
|
|
}
|
|
|
|
if (arg->flags & ~BTRFS_SEND_FLAG_MASK) {
|
|
- ret = -EINVAL;
|
|
+ ret = -EOPNOTSUPP;
|
|
goto out;
|
|
}
|
|
|
|
diff --git fs/cachefiles/bind.c fs/cachefiles/bind.c
|
|
index d9f001078e08..5aa9f4578f3e 100644
|
|
--- fs/cachefiles/bind.c
|
|
+++ fs/cachefiles/bind.c
|
|
@@ -248,6 +248,8 @@ error_open_root:
|
|
kmem_cache_free(cachefiles_object_jar, fsdef);
|
|
error_root_object:
|
|
cachefiles_end_secure(cache, saved_cred);
|
|
+ put_cred(cache->cache_cred);
|
|
+ cache->cache_cred = NULL;
|
|
pr_err("Failed to register: %d\n", ret);
|
|
return ret;
|
|
}
|
|
@@ -268,6 +270,7 @@ void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
|
|
|
|
dput(cache->graveyard);
|
|
mntput(cache->mnt);
|
|
+ put_cred(cache->cache_cred);
|
|
|
|
kfree(cache->rootdirname);
|
|
kfree(cache->secctx);
|
|
diff --git fs/ceph/caps.c fs/ceph/caps.c
|
|
index e36786f574b8..b84ce90953c6 100644
|
|
--- fs/ceph/caps.c
|
|
+++ fs/ceph/caps.c
|
|
@@ -4026,12 +4026,14 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry,
|
|
struct inode *dir,
|
|
int mds, int drop, int unless)
|
|
{
|
|
- struct dentry *parent = NULL;
|
|
struct ceph_mds_request_release *rel = *p;
|
|
struct ceph_dentry_info *di = ceph_dentry(dentry);
|
|
int force = 0;
|
|
int ret;
|
|
|
|
+ /* This shouldn't happen */
|
|
+ BUG_ON(!dir);
|
|
+
|
|
/*
|
|
* force an record for the directory caps if we have a dentry lease.
|
|
* this is racy (can't take i_ceph_lock and d_lock together), but it
|
|
@@ -4041,14 +4043,9 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry,
|
|
spin_lock(&dentry->d_lock);
|
|
if (di->lease_session && di->lease_session->s_mds == mds)
|
|
force = 1;
|
|
- if (!dir) {
|
|
- parent = dget(dentry->d_parent);
|
|
- dir = d_inode(parent);
|
|
- }
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
ret = ceph_encode_inode_release(p, dir, mds, drop, unless, force);
|
|
- dput(parent);
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
if (ret && di->lease_session && di->lease_session->s_mds == mds) {
|
|
diff --git fs/compat_ioctl.c fs/compat_ioctl.c
|
|
index f445bc9cdc94..74e8507419d7 100644
|
|
--- fs/compat_ioctl.c
|
|
+++ fs/compat_ioctl.c
|
|
@@ -1546,8 +1546,7 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
|
|
if (!f.file)
|
|
goto out;
|
|
|
|
- /* RED-PEN how should LSM module know it's handling 32bit? */
|
|
- error = security_file_ioctl(f.file, cmd, arg);
|
|
+ error = security_file_ioctl_compat(f.file, cmd, arg);
|
|
if (error)
|
|
goto out_fput;
|
|
|
|
diff --git fs/dcache.c fs/dcache.c
|
|
index 9ac1290ae44f..5a9a773ece54 100644
|
|
--- fs/dcache.c
|
|
+++ fs/dcache.c
|
|
@@ -709,12 +709,12 @@ static inline bool fast_dput(struct dentry *dentry)
|
|
*/
|
|
if (unlikely(ret < 0)) {
|
|
spin_lock(&dentry->d_lock);
|
|
- if (dentry->d_lockref.count > 1) {
|
|
- dentry->d_lockref.count--;
|
|
+ if (WARN_ON_ONCE(dentry->d_lockref.count <= 0)) {
|
|
spin_unlock(&dentry->d_lock);
|
|
return 1;
|
|
}
|
|
- return 0;
|
|
+ dentry->d_lockref.count--;
|
|
+ goto locked;
|
|
}
|
|
|
|
/*
|
|
@@ -765,6 +765,7 @@ static inline bool fast_dput(struct dentry *dentry)
|
|
* else could have killed it and marked it dead. Either way, we
|
|
* don't need to do anything else.
|
|
*/
|
|
+locked:
|
|
if (dentry->d_lockref.count) {
|
|
spin_unlock(&dentry->d_lock);
|
|
return 1;
|
|
diff --git fs/ext4/mballoc.c fs/ext4/mballoc.c
|
|
index 91d1de198fed..64ce26ec9c68 100644
|
|
--- fs/ext4/mballoc.c
|
|
+++ fs/ext4/mballoc.c
|
|
@@ -1817,6 +1817,9 @@ int ext4_mb_try_best_found(struct ext4_allocation_context *ac,
|
|
return err;
|
|
|
|
ext4_lock_group(ac->ac_sb, group);
|
|
+ if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
|
|
+ goto out;
|
|
+
|
|
max = mb_find_extent(e4b, ex.fe_start, ex.fe_len, &ex);
|
|
|
|
if (max > 0) {
|
|
@@ -1824,6 +1827,7 @@ int ext4_mb_try_best_found(struct ext4_allocation_context *ac,
|
|
ext4_mb_use_best_found(ac, e4b);
|
|
}
|
|
|
|
+out:
|
|
ext4_unlock_group(ac->ac_sb, group);
|
|
ext4_mb_unload_buddy(e4b);
|
|
|
|
@@ -1850,12 +1854,10 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
|
|
if (err)
|
|
return err;
|
|
|
|
- if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) {
|
|
- ext4_mb_unload_buddy(e4b);
|
|
- return 0;
|
|
- }
|
|
-
|
|
ext4_lock_group(ac->ac_sb, group);
|
|
+ if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
|
|
+ goto out;
|
|
+
|
|
max = mb_find_extent(e4b, ac->ac_g_ex.fe_start,
|
|
ac->ac_g_ex.fe_len, &ex);
|
|
ex.fe_logical = 0xDEADFA11; /* debug value */
|
|
@@ -1888,6 +1890,7 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
|
|
ac->ac_b_ex = ex;
|
|
ext4_mb_use_best_found(ac, e4b);
|
|
}
|
|
+out:
|
|
ext4_unlock_group(ac->ac_sb, group);
|
|
ext4_mb_unload_buddy(e4b);
|
|
|
|
diff --git fs/ext4/move_extent.c fs/ext4/move_extent.c
|
|
index ef60f2e92da6..a10c560405b2 100644
|
|
--- fs/ext4/move_extent.c
|
|
+++ fs/ext4/move_extent.c
|
|
@@ -628,6 +628,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
|
|
goto out;
|
|
o_end = o_start + len;
|
|
|
|
+ *moved_len = 0;
|
|
while (o_start < o_end) {
|
|
struct ext4_extent *ex;
|
|
ext4_lblk_t cur_blk, next_blk;
|
|
@@ -683,7 +684,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
|
|
*/
|
|
ext4_double_up_write_data_sem(orig_inode, donor_inode);
|
|
/* Swap original branches with new branches */
|
|
- move_extent_per_page(o_filp, donor_inode,
|
|
+ *moved_len += move_extent_per_page(o_filp, donor_inode,
|
|
orig_page_index, donor_page_index,
|
|
offset_in_page, cur_len,
|
|
unwritten, &ret);
|
|
@@ -693,9 +694,6 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
|
|
o_start += cur_len;
|
|
d_start += cur_len;
|
|
}
|
|
- *moved_len = o_start - orig_blk;
|
|
- if (*moved_len > len)
|
|
- *moved_len = len;
|
|
|
|
out:
|
|
if (*moved_len) {
|
|
diff --git fs/ext4/resize.c fs/ext4/resize.c
|
|
index f0b27be5892a..47ecf0826899 100644
|
|
--- fs/ext4/resize.c
|
|
+++ fs/ext4/resize.c
|
|
@@ -237,7 +237,7 @@ struct ext4_new_flex_group_data {
|
|
*
|
|
* Returns NULL on failure otherwise address of the allocated structure.
|
|
*/
|
|
-static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size)
|
|
+static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned int flexbg_size)
|
|
{
|
|
struct ext4_new_flex_group_data *flex_gd;
|
|
|
|
@@ -290,7 +290,7 @@ static void free_flex_gd(struct ext4_new_flex_group_data *flex_gd)
|
|
*/
|
|
static int ext4_alloc_group_tables(struct super_block *sb,
|
|
struct ext4_new_flex_group_data *flex_gd,
|
|
- int flexbg_size)
|
|
+ unsigned int flexbg_size)
|
|
{
|
|
struct ext4_new_group_data *group_data = flex_gd->groups;
|
|
ext4_fsblk_t start_blk;
|
|
@@ -383,12 +383,12 @@ next_group:
|
|
group = group_data[0].group;
|
|
|
|
printk(KERN_DEBUG "EXT4-fs: adding a flex group with "
|
|
- "%d groups, flexbg size is %d:\n", flex_gd->count,
|
|
+ "%u groups, flexbg size is %u:\n", flex_gd->count,
|
|
flexbg_size);
|
|
|
|
for (i = 0; i < flex_gd->count; i++) {
|
|
printk(KERN_DEBUG "adding %s group %u: %u "
|
|
- "blocks (%d free)\n",
|
|
+ "blocks (%u free)\n",
|
|
ext4_bg_has_super(sb, group + i) ? "normal" :
|
|
"no-super", group + i,
|
|
group_data[i].blocks_count,
|
|
@@ -1558,7 +1558,7 @@ exit:
|
|
static int ext4_setup_next_flex_gd(struct super_block *sb,
|
|
struct ext4_new_flex_group_data *flex_gd,
|
|
ext4_fsblk_t n_blocks_count,
|
|
- unsigned long flexbg_size)
|
|
+ unsigned int flexbg_size)
|
|
{
|
|
struct ext4_super_block *es = EXT4_SB(sb)->s_es;
|
|
struct ext4_new_group_data *group_data = flex_gd->groups;
|
|
@@ -1935,8 +1935,9 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
|
|
ext4_fsblk_t o_blocks_count;
|
|
ext4_fsblk_t n_blocks_count_retry = 0;
|
|
unsigned long last_update_time = 0;
|
|
- int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex;
|
|
+ int err = 0;
|
|
int meta_bg;
|
|
+ unsigned int flexbg_size = ext4_flex_bg_size(sbi);
|
|
|
|
/* See if the device is actually as big as what was requested */
|
|
bh = sb_bread(sb, n_blocks_count - 1);
|
|
diff --git fs/f2fs/namei.c fs/f2fs/namei.c
|
|
index 9fb98fce7096..eb9db586c01d 100644
|
|
--- fs/f2fs/namei.c
|
|
+++ fs/f2fs/namei.c
|
|
@@ -882,7 +882,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
}
|
|
|
|
if (old_dir_entry) {
|
|
- if (old_dir != new_dir && !whiteout) {
|
|
+ if (old_dir != new_dir) {
|
|
f2fs_set_link(old_inode, old_dir_entry,
|
|
old_dir_page, new_dir);
|
|
} else {
|
|
diff --git fs/f2fs/xattr.c fs/f2fs/xattr.c
|
|
index b3c64ab0d5a5..f52c01804f81 100644
|
|
--- fs/f2fs/xattr.c
|
|
+++ fs/f2fs/xattr.c
|
|
@@ -695,6 +695,12 @@ static int __f2fs_setxattr(struct inode *inode, int index,
|
|
memcpy(pval, value, size);
|
|
last->e_value_size = cpu_to_le16(size);
|
|
new_hsize += newsize;
|
|
+ /*
|
|
+ * Explicitly add the null terminator. The unused xattr space
|
|
+ * is supposed to always be zeroed, which would make this
|
|
+ * unnecessary, but don't depend on that.
|
|
+ */
|
|
+ *(u32 *)((u8 *)last + newsize) = 0;
|
|
}
|
|
|
|
error = write_all_xattrs(inode, new_hsize, base_addr, ipage);
|
|
diff --git fs/fuse/dir.c fs/fuse/dir.c
|
|
index 8e5125904762..bd602b7e8e46 100644
|
|
--- fs/fuse/dir.c
|
|
+++ fs/fuse/dir.c
|
|
@@ -1299,8 +1299,16 @@ retry:
|
|
dput(dentry);
|
|
dentry = alias;
|
|
}
|
|
- if (IS_ERR(dentry))
|
|
+ if (IS_ERR(dentry)) {
|
|
+ if (!IS_ERR(inode)) {
|
|
+ struct fuse_inode *fi = get_fuse_inode(inode);
|
|
+
|
|
+ spin_lock(&fc->lock);
|
|
+ fi->nlookup--;
|
|
+ spin_unlock(&fc->lock);
|
|
+ }
|
|
return PTR_ERR(dentry);
|
|
+ }
|
|
}
|
|
if (fc->readdirplus_auto)
|
|
set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
|
|
diff --git fs/jbd2/journal.c fs/jbd2/journal.c
|
|
index 93a466cf58ba..ee114f0b625a 100644
|
|
--- fs/jbd2/journal.c
|
|
+++ fs/jbd2/journal.c
|
|
@@ -1361,9 +1361,11 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags)
|
|
return -EIO;
|
|
}
|
|
|
|
- trace_jbd2_write_superblock(journal, write_flags);
|
|
if (!(journal->j_flags & JBD2_BARRIER))
|
|
write_flags &= ~(REQ_FUA | REQ_PREFLUSH);
|
|
+
|
|
+ trace_jbd2_write_superblock(journal, write_flags);
|
|
+
|
|
if (buffer_write_io_error(bh)) {
|
|
/*
|
|
* Oh, dear. A previous attempt to write the journal
|
|
diff --git fs/jfs/jfs_dmap.c fs/jfs/jfs_dmap.c
|
|
index ed7989d7b2ba..6c6efb5a168b 100644
|
|
--- fs/jfs/jfs_dmap.c
|
|
+++ fs/jfs/jfs_dmap.c
|
|
@@ -76,10 +76,10 @@
|
|
*/
|
|
static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
|
|
int nblocks);
|
|
-static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval);
|
|
-static int dbBackSplit(dmtree_t * tp, int leafno);
|
|
-static int dbJoin(dmtree_t * tp, int leafno, int newval);
|
|
-static void dbAdjTree(dmtree_t * tp, int leafno, int newval);
|
|
+static void dbSplit(dmtree_t *tp, int leafno, int splitsz, int newval, bool is_ctl);
|
|
+static int dbBackSplit(dmtree_t *tp, int leafno, bool is_ctl);
|
|
+static int dbJoin(dmtree_t *tp, int leafno, int newval, bool is_ctl);
|
|
+static void dbAdjTree(dmtree_t *tp, int leafno, int newval, bool is_ctl);
|
|
static int dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc,
|
|
int level);
|
|
static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results);
|
|
@@ -2184,7 +2184,7 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
|
|
* system.
|
|
*/
|
|
if (dp->tree.stree[word] == NOFREE)
|
|
- dbBackSplit((dmtree_t *) & dp->tree, word);
|
|
+ dbBackSplit((dmtree_t *)&dp->tree, word, false);
|
|
|
|
dbAllocBits(bmp, dp, blkno, nblocks);
|
|
}
|
|
@@ -2270,7 +2270,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
|
|
* the binary system of the leaves if need be.
|
|
*/
|
|
dbSplit(tp, word, BUDMIN,
|
|
- dbMaxBud((u8 *) & dp->wmap[word]));
|
|
+ dbMaxBud((u8 *)&dp->wmap[word]), false);
|
|
|
|
word += 1;
|
|
} else {
|
|
@@ -2310,7 +2310,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
|
|
* system of the leaves to reflect the current
|
|
* allocation (size).
|
|
*/
|
|
- dbSplit(tp, word, size, NOFREE);
|
|
+ dbSplit(tp, word, size, NOFREE, false);
|
|
|
|
/* get the number of dmap words handled */
|
|
nw = BUDSIZE(size, BUDMIN);
|
|
@@ -2417,7 +2417,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
|
|
/* update the leaf for this dmap word.
|
|
*/
|
|
rc = dbJoin(tp, word,
|
|
- dbMaxBud((u8 *) & dp->wmap[word]));
|
|
+ dbMaxBud((u8 *)&dp->wmap[word]), false);
|
|
if (rc)
|
|
return rc;
|
|
|
|
@@ -2450,7 +2450,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
|
|
|
|
/* update the leaf.
|
|
*/
|
|
- rc = dbJoin(tp, word, size);
|
|
+ rc = dbJoin(tp, word, size, false);
|
|
if (rc)
|
|
return rc;
|
|
|
|
@@ -2602,14 +2602,14 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
|
|
* that it is at the front of a binary buddy system.
|
|
*/
|
|
if (oldval == NOFREE) {
|
|
- rc = dbBackSplit((dmtree_t *) dcp, leafno);
|
|
+ rc = dbBackSplit((dmtree_t *)dcp, leafno, true);
|
|
if (rc)
|
|
return rc;
|
|
oldval = dcp->stree[ti];
|
|
}
|
|
- dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval);
|
|
+ dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval, true);
|
|
} else {
|
|
- rc = dbJoin((dmtree_t *) dcp, leafno, newval);
|
|
+ rc = dbJoin((dmtree_t *) dcp, leafno, newval, true);
|
|
if (rc)
|
|
return rc;
|
|
}
|
|
@@ -2638,7 +2638,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
|
|
*/
|
|
if (alloc) {
|
|
dbJoin((dmtree_t *) dcp, leafno,
|
|
- oldval);
|
|
+ oldval, true);
|
|
} else {
|
|
/* the dbJoin() above might have
|
|
* caused a larger binary buddy system
|
|
@@ -2648,9 +2648,9 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
|
|
*/
|
|
if (dcp->stree[ti] == NOFREE)
|
|
dbBackSplit((dmtree_t *)
|
|
- dcp, leafno);
|
|
+ dcp, leafno, true);
|
|
dbSplit((dmtree_t *) dcp, leafno,
|
|
- dcp->budmin, oldval);
|
|
+ dcp->budmin, oldval, true);
|
|
}
|
|
|
|
/* release the buffer and return the error.
|
|
@@ -2698,7 +2698,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
|
|
*
|
|
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
|
|
*/
|
|
-static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
|
|
+static void dbSplit(dmtree_t *tp, int leafno, int splitsz, int newval, bool is_ctl)
|
|
{
|
|
int budsz;
|
|
int cursz;
|
|
@@ -2720,7 +2720,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
|
|
while (cursz >= splitsz) {
|
|
/* update the buddy's leaf with its new value.
|
|
*/
|
|
- dbAdjTree(tp, leafno ^ budsz, cursz);
|
|
+ dbAdjTree(tp, leafno ^ budsz, cursz, is_ctl);
|
|
|
|
/* on to the next size and buddy.
|
|
*/
|
|
@@ -2732,7 +2732,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
|
|
/* adjust the dmap tree to reflect the specified leaf's new
|
|
* value.
|
|
*/
|
|
- dbAdjTree(tp, leafno, newval);
|
|
+ dbAdjTree(tp, leafno, newval, is_ctl);
|
|
}
|
|
|
|
|
|
@@ -2763,7 +2763,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
|
|
*
|
|
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
|
|
*/
|
|
-static int dbBackSplit(dmtree_t * tp, int leafno)
|
|
+static int dbBackSplit(dmtree_t *tp, int leafno, bool is_ctl)
|
|
{
|
|
int budsz, bud, w, bsz, size;
|
|
int cursz;
|
|
@@ -2814,7 +2814,7 @@ static int dbBackSplit(dmtree_t * tp, int leafno)
|
|
* system in two.
|
|
*/
|
|
cursz = leaf[bud] - 1;
|
|
- dbSplit(tp, bud, cursz, cursz);
|
|
+ dbSplit(tp, bud, cursz, cursz, is_ctl);
|
|
break;
|
|
}
|
|
}
|
|
@@ -2842,7 +2842,7 @@ static int dbBackSplit(dmtree_t * tp, int leafno)
|
|
*
|
|
* RETURN VALUES: none
|
|
*/
|
|
-static int dbJoin(dmtree_t * tp, int leafno, int newval)
|
|
+static int dbJoin(dmtree_t *tp, int leafno, int newval, bool is_ctl)
|
|
{
|
|
int budsz, buddy;
|
|
s8 *leaf;
|
|
@@ -2897,12 +2897,12 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
|
|
if (leafno < buddy) {
|
|
/* leafno is the left buddy.
|
|
*/
|
|
- dbAdjTree(tp, buddy, NOFREE);
|
|
+ dbAdjTree(tp, buddy, NOFREE, is_ctl);
|
|
} else {
|
|
/* buddy is the left buddy and becomes
|
|
* leafno.
|
|
*/
|
|
- dbAdjTree(tp, leafno, NOFREE);
|
|
+ dbAdjTree(tp, leafno, NOFREE, is_ctl);
|
|
leafno = buddy;
|
|
}
|
|
|
|
@@ -2915,7 +2915,7 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
|
|
|
|
/* update the leaf value.
|
|
*/
|
|
- dbAdjTree(tp, leafno, newval);
|
|
+ dbAdjTree(tp, leafno, newval, is_ctl);
|
|
|
|
return 0;
|
|
}
|
|
@@ -2936,15 +2936,20 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
|
|
*
|
|
* RETURN VALUES: none
|
|
*/
|
|
-static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
|
|
+static void dbAdjTree(dmtree_t *tp, int leafno, int newval, bool is_ctl)
|
|
{
|
|
int lp, pp, k;
|
|
- int max;
|
|
+ int max, size;
|
|
+
|
|
+ size = is_ctl ? CTLTREESIZE : TREESIZE;
|
|
|
|
/* pick up the index of the leaf for this leafno.
|
|
*/
|
|
lp = leafno + le32_to_cpu(tp->dmt_leafidx);
|
|
|
|
+ if (WARN_ON_ONCE(lp >= size || lp < 0))
|
|
+ return;
|
|
+
|
|
/* is the current value the same as the old value ? if so,
|
|
* there is nothing to do.
|
|
*/
|
|
diff --git fs/jfs/jfs_dtree.c fs/jfs/jfs_dtree.c
|
|
index de2bcb36e079..14a16bb906e8 100644
|
|
--- fs/jfs/jfs_dtree.c
|
|
+++ fs/jfs/jfs_dtree.c
|
|
@@ -645,6 +645,11 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
|
|
for (base = 0, lim = p->header.nextindex; lim; lim >>= 1) {
|
|
index = base + (lim >> 1);
|
|
|
|
+ if (stbl[index] < 0) {
|
|
+ rc = -EIO;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
if (p->header.flag & BT_LEAF) {
|
|
/* uppercase leaf name to compare */
|
|
cmp =
|
|
@@ -1982,7 +1987,7 @@ static int dtSplitRoot(tid_t tid,
|
|
do {
|
|
f = &rp->slot[fsi];
|
|
fsi = f->next;
|
|
- } while (fsi != -1);
|
|
+ } while (fsi >= 0);
|
|
|
|
f->next = n;
|
|
}
|
|
diff --git fs/jfs/jfs_imap.c fs/jfs/jfs_imap.c
|
|
index 131dce5316ac..5cdcf68a4803 100644
|
|
--- fs/jfs/jfs_imap.c
|
|
+++ fs/jfs/jfs_imap.c
|
|
@@ -2200,6 +2200,9 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
|
|
/* get the ag and iag numbers for this iag.
|
|
*/
|
|
agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);
|
|
+ if (agno >= MAXAG || agno < 0)
|
|
+ return -EIO;
|
|
+
|
|
iagno = le32_to_cpu(iagp->iagnum);
|
|
|
|
/* check if this is the last free extent within the
|
|
diff --git fs/jfs/jfs_mount.c fs/jfs/jfs_mount.c
|
|
index f1a705d15904..97d91c1686b8 100644
|
|
--- fs/jfs/jfs_mount.c
|
|
+++ fs/jfs/jfs_mount.c
|
|
@@ -184,15 +184,15 @@ int jfs_mount(struct super_block *sb)
|
|
}
|
|
jfs_info("jfs_mount: ipimap:0x%p", ipimap);
|
|
|
|
- /* map further access of per fileset inodes by the fileset inode */
|
|
- sbi->ipimap = ipimap;
|
|
-
|
|
/* initialize fileset inode allocation map */
|
|
if ((rc = diMount(ipimap))) {
|
|
jfs_err("jfs_mount: diMount failed w/rc = %d", rc);
|
|
goto err_ipimap;
|
|
}
|
|
|
|
+ /* map further access of per fileset inodes by the fileset inode */
|
|
+ sbi->ipimap = ipimap;
|
|
+
|
|
return rc;
|
|
|
|
/*
|
|
diff --git fs/nfs/nfs4proc.c fs/nfs/nfs4proc.c
|
|
index ff41d726f758..77c207a0fb81 100644
|
|
--- fs/nfs/nfs4proc.c
|
|
+++ fs/nfs/nfs4proc.c
|
|
@@ -161,6 +161,7 @@ static int nfs4_map_errors(int err)
|
|
case -NFS4ERR_RESOURCE:
|
|
case -NFS4ERR_LAYOUTTRYLATER:
|
|
case -NFS4ERR_RECALLCONFLICT:
|
|
+ case -NFS4ERR_RETURNCONFLICT:
|
|
return -EREMOTEIO;
|
|
case -NFS4ERR_WRONGSEC:
|
|
case -NFS4ERR_WRONG_CRED:
|
|
@@ -472,6 +473,7 @@ static int nfs4_do_handle_exception(struct nfs_server *server,
|
|
case -NFS4ERR_GRACE:
|
|
case -NFS4ERR_LAYOUTTRYLATER:
|
|
case -NFS4ERR_RECALLCONFLICT:
|
|
+ case -NFS4ERR_RETURNCONFLICT:
|
|
exception->delay = 1;
|
|
return 0;
|
|
|
|
@@ -8540,6 +8542,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
|
|
status = -EBUSY;
|
|
break;
|
|
case -NFS4ERR_RECALLCONFLICT:
|
|
+ case -NFS4ERR_RETURNCONFLICT:
|
|
status = -ERECALLCONFLICT;
|
|
break;
|
|
case -NFS4ERR_DELEG_REVOKED:
|
|
diff --git fs/nfsd/nfs4state.c fs/nfsd/nfs4state.c
|
|
index 2adbf471d107..6720c82ac351 100644
|
|
--- fs/nfsd/nfs4state.c
|
|
+++ fs/nfsd/nfs4state.c
|
|
@@ -6351,12 +6351,16 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
|
|
if (sop->so_is_open_owner || !same_owner_str(sop, owner))
|
|
continue;
|
|
|
|
- if (atomic_read(&sop->so_count) != 1) {
|
|
- spin_unlock(&clp->cl_lock);
|
|
- return nfserr_locks_held;
|
|
+ /* see if there are still any locks associated with it */
|
|
+ lo = lockowner(sop);
|
|
+ list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) {
|
|
+ if (check_for_locks(stp->st_stid.sc_file, lo)) {
|
|
+ status = nfserr_locks_held;
|
|
+ spin_unlock(&clp->cl_lock);
|
|
+ return status;
|
|
+ }
|
|
}
|
|
|
|
- lo = lockowner(sop);
|
|
nfs4_get_stateowner(sop);
|
|
break;
|
|
}
|
|
diff --git fs/nilfs2/dat.c fs/nilfs2/dat.c
|
|
index 185db3c3033b..63bd20032fa7 100644
|
|
--- fs/nilfs2/dat.c
|
|
+++ fs/nilfs2/dat.c
|
|
@@ -49,8 +49,21 @@ static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat)
|
|
static int nilfs_dat_prepare_entry(struct inode *dat,
|
|
struct nilfs_palloc_req *req, int create)
|
|
{
|
|
- return nilfs_palloc_get_entry_block(dat, req->pr_entry_nr,
|
|
- create, &req->pr_entry_bh);
|
|
+ int ret;
|
|
+
|
|
+ ret = nilfs_palloc_get_entry_block(dat, req->pr_entry_nr,
|
|
+ create, &req->pr_entry_bh);
|
|
+ if (unlikely(ret == -ENOENT)) {
|
|
+ nilfs_msg(dat->i_sb, KERN_ERR,
|
|
+ "DAT doesn't have a block to manage vblocknr = %llu",
|
|
+ (unsigned long long)req->pr_entry_nr);
|
|
+ /*
|
|
+ * Return internal code -EINVAL to notify bmap layer of
|
|
+ * metadata corruption.
|
|
+ */
|
|
+ ret = -EINVAL;
|
|
+ }
|
|
+ return ret;
|
|
}
|
|
|
|
static void nilfs_dat_commit_entry(struct inode *dat,
|
|
@@ -132,11 +145,7 @@ static void nilfs_dat_commit_free(struct inode *dat,
|
|
|
|
int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req)
|
|
{
|
|
- int ret;
|
|
-
|
|
- ret = nilfs_dat_prepare_entry(dat, req, 0);
|
|
- WARN_ON(ret == -ENOENT);
|
|
- return ret;
|
|
+ return nilfs_dat_prepare_entry(dat, req, 0);
|
|
}
|
|
|
|
void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
|
|
@@ -163,10 +172,8 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
|
|
int ret;
|
|
|
|
ret = nilfs_dat_prepare_entry(dat, req, 0);
|
|
- if (ret < 0) {
|
|
- WARN_ON(ret == -ENOENT);
|
|
+ if (ret < 0)
|
|
return ret;
|
|
- }
|
|
|
|
kaddr = kmap_atomic(req->pr_entry_bh->b_page);
|
|
entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
|
|
diff --git fs/nilfs2/file.c fs/nilfs2/file.c
|
|
index c5fa3dee72fc..43501da7ef66 100644
|
|
--- fs/nilfs2/file.c
|
|
+++ fs/nilfs2/file.c
|
|
@@ -114,7 +114,13 @@ static int nilfs_page_mkwrite(struct vm_fault *vmf)
|
|
nilfs_transaction_commit(inode->i_sb);
|
|
|
|
mapped:
|
|
- wait_for_stable_page(page);
|
|
+ /*
|
|
+ * Since checksumming including data blocks is performed to determine
|
|
+ * the validity of the log to be written and used for recovery, it is
|
|
+ * necessary to wait for writeback to finish here, regardless of the
|
|
+ * stable write requirement of the backing device.
|
|
+ */
|
|
+ wait_on_page_writeback(page);
|
|
out:
|
|
sb_end_pagefault(inode->i_sb);
|
|
return block_page_mkwrite_return(ret);
|
|
diff --git fs/nilfs2/recovery.c fs/nilfs2/recovery.c
|
|
index 5139efed1888..cff597333afe 100644
|
|
--- fs/nilfs2/recovery.c
|
|
+++ fs/nilfs2/recovery.c
|
|
@@ -481,9 +481,10 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
|
|
|
|
static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
|
|
struct nilfs_recovery_block *rb,
|
|
- struct page *page)
|
|
+ loff_t pos, struct page *page)
|
|
{
|
|
struct buffer_head *bh_org;
|
|
+ size_t from = pos & ~PAGE_MASK;
|
|
void *kaddr;
|
|
|
|
bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize);
|
|
@@ -491,7 +492,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
|
|
return -EIO;
|
|
|
|
kaddr = kmap_atomic(page);
|
|
- memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
|
|
+ memcpy(kaddr + from, bh_org->b_data, bh_org->b_size);
|
|
kunmap_atomic(kaddr);
|
|
brelse(bh_org);
|
|
return 0;
|
|
@@ -530,7 +531,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
|
|
goto failed_inode;
|
|
}
|
|
|
|
- err = nilfs_recovery_copy_block(nilfs, rb, page);
|
|
+ err = nilfs_recovery_copy_block(nilfs, rb, pos, page);
|
|
if (unlikely(err))
|
|
goto failed_page;
|
|
|
|
diff --git fs/nilfs2/segment.c fs/nilfs2/segment.c
|
|
index ca4b1675c147..b9fd60e07701 100644
|
|
--- fs/nilfs2/segment.c
|
|
+++ fs/nilfs2/segment.c
|
|
@@ -1715,7 +1715,6 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci)
|
|
|
|
list_for_each_entry(bh, &segbuf->sb_payload_buffers,
|
|
b_assoc_buffers) {
|
|
- set_buffer_async_write(bh);
|
|
if (bh == segbuf->sb_super_root) {
|
|
if (bh->b_page != bd_page) {
|
|
lock_page(bd_page);
|
|
@@ -1726,6 +1725,7 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci)
|
|
}
|
|
break;
|
|
}
|
|
+ set_buffer_async_write(bh);
|
|
if (bh->b_page != fs_page) {
|
|
nilfs_begin_page_io(fs_page);
|
|
fs_page = bh->b_page;
|
|
@@ -1811,7 +1811,6 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
|
|
|
|
list_for_each_entry(bh, &segbuf->sb_payload_buffers,
|
|
b_assoc_buffers) {
|
|
- clear_buffer_async_write(bh);
|
|
if (bh == segbuf->sb_super_root) {
|
|
clear_buffer_uptodate(bh);
|
|
if (bh->b_page != bd_page) {
|
|
@@ -1820,6 +1819,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
|
|
}
|
|
break;
|
|
}
|
|
+ clear_buffer_async_write(bh);
|
|
if (bh->b_page != fs_page) {
|
|
nilfs_end_page_io(fs_page, err);
|
|
fs_page = bh->b_page;
|
|
@@ -1907,8 +1907,9 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
|
|
BIT(BH_Delay) | BIT(BH_NILFS_Volatile) |
|
|
BIT(BH_NILFS_Redirected));
|
|
|
|
- set_mask_bits(&bh->b_state, clear_bits, set_bits);
|
|
if (bh == segbuf->sb_super_root) {
|
|
+ set_buffer_uptodate(bh);
|
|
+ clear_buffer_dirty(bh);
|
|
if (bh->b_page != bd_page) {
|
|
end_page_writeback(bd_page);
|
|
bd_page = bh->b_page;
|
|
@@ -1916,6 +1917,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
|
|
update_sr = true;
|
|
break;
|
|
}
|
|
+ set_mask_bits(&bh->b_state, clear_bits, set_bits);
|
|
if (bh->b_page != fs_page) {
|
|
nilfs_end_page_io(fs_page, 0);
|
|
fs_page = bh->b_page;
|
|
diff --git fs/pstore/ram.c fs/pstore/ram.c
|
|
index dc5a40058c2f..bbd90fef7fcd 100644
|
|
--- fs/pstore/ram.c
|
|
+++ fs/pstore/ram.c
|
|
@@ -586,6 +586,7 @@ static int ramoops_init_przs(const char *name,
|
|
}
|
|
|
|
zone_sz = mem_sz / *cnt;
|
|
+ zone_sz = ALIGN_DOWN(zone_sz, 2);
|
|
if (!zone_sz) {
|
|
dev_err(dev, "%s zone size == 0\n", name);
|
|
goto fail;
|
|
diff --git fs/pstore/ram_core.c fs/pstore/ram_core.c
|
|
index 58ac4e1a61a3..a323ed939aa8 100644
|
|
--- fs/pstore/ram_core.c
|
|
+++ fs/pstore/ram_core.c
|
|
@@ -190,7 +190,7 @@ static int persistent_ram_init_ecc(struct persistent_ram_zone *prz,
|
|
{
|
|
int numerr;
|
|
struct persistent_ram_buffer *buffer = prz->buffer;
|
|
- int ecc_blocks;
|
|
+ size_t ecc_blocks;
|
|
size_t ecc_total;
|
|
|
|
if (!ecc_info || !ecc_info->ecc_size)
|
|
diff --git include/crypto/if_alg.h include/crypto/if_alg.h
|
|
index 2ea6a95ca825..f803dc8c45ad 100644
|
|
--- include/crypto/if_alg.h
|
|
+++ include/crypto/if_alg.h
|
|
@@ -146,6 +146,7 @@ struct af_alg_async_req {
|
|
* @enc: Cryptographic operation to be performed when
|
|
* recvmsg is invoked.
|
|
* @len: Length of memory allocated for this data structure.
|
|
+ * @inflight: Non-zero when AIO requests are in flight.
|
|
*/
|
|
struct af_alg_ctx {
|
|
struct list_head tsgl_list;
|
|
@@ -163,6 +164,8 @@ struct af_alg_ctx {
|
|
bool enc;
|
|
|
|
unsigned int len;
|
|
+
|
|
+ unsigned int inflight;
|
|
};
|
|
|
|
int af_alg_register_type(const struct af_alg_type *type);
|
|
diff --git include/drm/drm_bridge.h include/drm/drm_bridge.h
|
|
index 6522d4cbc9d9..bfbd38c0b609 100644
|
|
--- include/drm/drm_bridge.h
|
|
+++ include/drm/drm_bridge.h
|
|
@@ -161,7 +161,7 @@ struct drm_bridge_funcs {
|
|
* or &drm_encoder_helper_funcs.dpms hook.
|
|
*
|
|
* The bridge must assume that the display pipe (i.e. clocks and timing
|
|
- * singals) feeding it is no longer running when this callback is
|
|
+ * signals) feeding it is no longer running when this callback is
|
|
* called.
|
|
*
|
|
* The post_disable callback is optional.
|
|
diff --git include/drm/drm_mipi_dsi.h include/drm/drm_mipi_dsi.h
|
|
index 689f615471ab..a059f1d968b7 100644
|
|
--- include/drm/drm_mipi_dsi.h
|
|
+++ include/drm/drm_mipi_dsi.h
|
|
@@ -163,6 +163,7 @@ struct mipi_dsi_device_info {
|
|
* struct mipi_dsi_device - DSI peripheral device
|
|
* @host: DSI host for this peripheral
|
|
* @dev: driver model device node for this peripheral
|
|
+ * @attached: the DSI device has been successfully attached
|
|
* @name: DSI peripheral chip type
|
|
* @channel: virtual channel assigned to the peripheral
|
|
* @format: pixel format for video mode
|
|
@@ -172,6 +173,7 @@ struct mipi_dsi_device_info {
|
|
struct mipi_dsi_device {
|
|
struct mipi_dsi_host *host;
|
|
struct device dev;
|
|
+ bool attached;
|
|
|
|
char name[DSI_DEV_NAME_SIZE];
|
|
unsigned int channel;
|
|
diff --git include/linux/bpf.h include/linux/bpf.h
|
|
index 3aa05ea79ba1..0d7a61df056b 100644
|
|
--- include/linux/bpf.h
|
|
+++ include/linux/bpf.h
|
|
@@ -38,7 +38,11 @@ struct bpf_map_ops {
|
|
/* funcs called by prog_array and perf_event_array map */
|
|
void *(*map_fd_get_ptr)(struct bpf_map *map, struct file *map_file,
|
|
int fd);
|
|
- void (*map_fd_put_ptr)(void *ptr);
|
|
+ /* If need_defer is true, the implementation should guarantee that
|
|
+ * the to-be-put element is still alive before the bpf program, which
|
|
+ * may manipulate it, exists.
|
|
+ */
|
|
+ void (*map_fd_put_ptr)(struct bpf_map *map, void *ptr, bool need_defer);
|
|
u32 (*map_gen_lookup)(struct bpf_map *map, struct bpf_insn *insn_buf);
|
|
u32 (*map_fd_sys_lookup_elem)(void *ptr);
|
|
};
|
|
diff --git include/linux/device.h include/linux/device.h
|
|
index 65e06a066b67..27b70b810463 100644
|
|
--- include/linux/device.h
|
|
+++ include/linux/device.h
|
|
@@ -1474,6 +1474,9 @@ do { \
|
|
WARN_ONCE(condition, "%s %s: " format, \
|
|
dev_driver_string(dev), dev_name(dev), ## arg)
|
|
|
|
+extern __printf(3, 4)
|
|
+int dev_err_probe(const struct device *dev, int err, const char *fmt, ...);
|
|
+
|
|
/* Create alias, so I can be autoloaded. */
|
|
#define MODULE_ALIAS_CHARDEV(major,minor) \
|
|
MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
|
|
diff --git include/linux/dmaengine.h include/linux/dmaengine.h
|
|
index 8089e28539f1..d5a7d320e05c 100644
|
|
--- include/linux/dmaengine.h
|
|
+++ include/linux/dmaengine.h
|
|
@@ -816,7 +816,8 @@ static inline int dmaengine_slave_config(struct dma_chan *chan,
|
|
|
|
static inline bool is_slave_direction(enum dma_transfer_direction direction)
|
|
{
|
|
- return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM);
|
|
+ return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM) ||
|
|
+ (direction == DMA_DEV_TO_DEV);
|
|
}
|
|
|
|
static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
|
|
diff --git include/linux/fs.h include/linux/fs.h
|
|
index ff0a992846a3..bd6072556269 100644
|
|
--- include/linux/fs.h
|
|
+++ include/linux/fs.h
|
|
@@ -296,6 +296,8 @@ enum rw_hint {
|
|
#define IOCB_SYNC (1 << 5)
|
|
#define IOCB_WRITE (1 << 6)
|
|
#define IOCB_NOWAIT (1 << 7)
|
|
+/* kiocb is a read or write operation submitted by fs/aio.c. */
|
|
+#define IOCB_AIO_RW (1 << 23)
|
|
|
|
struct kiocb {
|
|
struct file *ki_filp;
|
|
diff --git include/linux/lsm_hooks.h include/linux/lsm_hooks.h
|
|
index 569debc49f3d..28ff40daccff 100644
|
|
--- include/linux/lsm_hooks.h
|
|
+++ include/linux/lsm_hooks.h
|
|
@@ -466,6 +466,12 @@
|
|
* simple integer value. When @arg represents a user space pointer, it
|
|
* should never be used by the security module.
|
|
* Return 0 if permission is granted.
|
|
+ * @file_ioctl_compat:
|
|
+ * @file contains the file structure.
|
|
+ * @cmd contains the operation to perform.
|
|
+ * @arg contains the operational arguments.
|
|
+ * Check permission for a compat ioctl operation on @file.
|
|
+ * Return 0 if permission is granted.
|
|
* @mmap_addr :
|
|
* Check permissions for a mmap operation at @addr.
|
|
* @addr contains virtual address that will be used for the operation.
|
|
@@ -1486,6 +1492,8 @@ union security_list_options {
|
|
void (*file_free_security)(struct file *file);
|
|
int (*file_ioctl)(struct file *file, unsigned int cmd,
|
|
unsigned long arg);
|
|
+ int (*file_ioctl_compat)(struct file *file, unsigned int cmd,
|
|
+ unsigned long arg);
|
|
int (*mmap_addr)(unsigned long addr);
|
|
int (*mmap_file)(struct file *file, unsigned long reqprot,
|
|
unsigned long prot, unsigned long flags);
|
|
@@ -1764,6 +1772,7 @@ struct security_hook_heads {
|
|
struct list_head file_alloc_security;
|
|
struct list_head file_free_security;
|
|
struct list_head file_ioctl;
|
|
+ struct list_head file_ioctl_compat;
|
|
struct list_head mmap_addr;
|
|
struct list_head mmap_file;
|
|
struct list_head file_mprotect;
|
|
diff --git include/linux/pci_ids.h include/linux/pci_ids.h
|
|
index 83f576d45d78..c977e636a1dd 100644
|
|
--- include/linux/pci_ids.h
|
|
+++ include/linux/pci_ids.h
|
|
@@ -2953,6 +2953,7 @@
|
|
#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0
|
|
#define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2
|
|
#define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601
|
|
+#define PCI_DEVICE_ID_INTEL_HDA_ARL 0x7728
|
|
#define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119
|
|
#define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a
|
|
#define PCI_DEVICE_ID_INTEL_E6XX_CU 0x8183
|
|
diff --git include/linux/security.h include/linux/security.h
|
|
index 1c8968a267c2..cf77cd971795 100644
|
|
--- include/linux/security.h
|
|
+++ include/linux/security.h
|
|
@@ -306,6 +306,8 @@ int security_file_permission(struct file *file, int mask);
|
|
int security_file_alloc(struct file *file);
|
|
void security_file_free(struct file *file);
|
|
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
|
+int security_file_ioctl_compat(struct file *file, unsigned int cmd,
|
|
+ unsigned long arg);
|
|
int security_mmap_file(struct file *file, unsigned long prot,
|
|
unsigned long flags);
|
|
int security_mmap_addr(unsigned long addr);
|
|
@@ -827,6 +829,13 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd,
|
|
return 0;
|
|
}
|
|
|
|
+static inline int security_file_ioctl_compat(struct file *file,
|
|
+ unsigned int cmd,
|
|
+ unsigned long arg)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static inline int security_mmap_file(struct file *file, unsigned long prot,
|
|
unsigned long flags)
|
|
{
|
|
diff --git include/linux/spi/spi.h include/linux/spi/spi.h
|
|
index a8f6606dd498..5c7741ca3b99 100644
|
|
--- include/linux/spi/spi.h
|
|
+++ include/linux/spi/spi.h
|
|
@@ -153,6 +153,7 @@ struct spi_device {
|
|
#define SPI_MODE_1 (0|SPI_CPHA)
|
|
#define SPI_MODE_2 (SPI_CPOL|0)
|
|
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
|
|
+#define SPI_MODE_X_MASK (SPI_CPOL|SPI_CPHA)
|
|
#define SPI_CS_HIGH 0x04 /* chipselect active high? */
|
|
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
|
|
#define SPI_3WIRE 0x10 /* SI/SO signals shared */
|
|
diff --git include/linux/units.h include/linux/units.h
|
|
new file mode 100644
|
|
index 000000000000..a0af6d2ef4e5
|
|
--- /dev/null
|
|
+++ include/linux/units.h
|
|
@@ -0,0 +1,92 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+#ifndef _LINUX_UNITS_H
|
|
+#define _LINUX_UNITS_H
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+
|
|
+#define HZ_PER_KHZ 1000UL
|
|
+#define KHZ_PER_MHZ 1000UL
|
|
+#define HZ_PER_MHZ 1000000UL
|
|
+
|
|
+#define MILLIWATT_PER_WATT 1000UL
|
|
+#define MICROWATT_PER_MILLIWATT 1000UL
|
|
+#define MICROWATT_PER_WATT 1000000UL
|
|
+
|
|
+#define ABSOLUTE_ZERO_MILLICELSIUS -273150
|
|
+
|
|
+static inline long milli_kelvin_to_millicelsius(long t)
|
|
+{
|
|
+ return t + ABSOLUTE_ZERO_MILLICELSIUS;
|
|
+}
|
|
+
|
|
+static inline long millicelsius_to_milli_kelvin(long t)
|
|
+{
|
|
+ return t - ABSOLUTE_ZERO_MILLICELSIUS;
|
|
+}
|
|
+
|
|
+#define MILLIDEGREE_PER_DEGREE 1000
|
|
+#define MILLIDEGREE_PER_DECIDEGREE 100
|
|
+
|
|
+static inline long kelvin_to_millicelsius(long t)
|
|
+{
|
|
+ return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DEGREE);
|
|
+}
|
|
+
|
|
+static inline long millicelsius_to_kelvin(long t)
|
|
+{
|
|
+ t = millicelsius_to_milli_kelvin(t);
|
|
+
|
|
+ return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE);
|
|
+}
|
|
+
|
|
+static inline long deci_kelvin_to_celsius(long t)
|
|
+{
|
|
+ t = milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE);
|
|
+
|
|
+ return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE);
|
|
+}
|
|
+
|
|
+static inline long celsius_to_deci_kelvin(long t)
|
|
+{
|
|
+ t = millicelsius_to_milli_kelvin(t * MILLIDEGREE_PER_DEGREE);
|
|
+
|
|
+ return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * deci_kelvin_to_millicelsius_with_offset - convert Kelvin to Celsius
|
|
+ * @t: temperature value in decidegrees Kelvin
|
|
+ * @offset: difference between Kelvin and Celsius in millidegrees
|
|
+ *
|
|
+ * Return: temperature value in millidegrees Celsius
|
|
+ */
|
|
+static inline long deci_kelvin_to_millicelsius_with_offset(long t, long offset)
|
|
+{
|
|
+ return t * MILLIDEGREE_PER_DECIDEGREE - offset;
|
|
+}
|
|
+
|
|
+static inline long deci_kelvin_to_millicelsius(long t)
|
|
+{
|
|
+ return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE);
|
|
+}
|
|
+
|
|
+static inline long millicelsius_to_deci_kelvin(long t)
|
|
+{
|
|
+ t = millicelsius_to_milli_kelvin(t);
|
|
+
|
|
+ return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE);
|
|
+}
|
|
+
|
|
+static inline long kelvin_to_celsius(long t)
|
|
+{
|
|
+ return t + DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS,
|
|
+ MILLIDEGREE_PER_DEGREE);
|
|
+}
|
|
+
|
|
+static inline long celsius_to_kelvin(long t)
|
|
+{
|
|
+ return t - DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS,
|
|
+ MILLIDEGREE_PER_DEGREE);
|
|
+}
|
|
+
|
|
+#endif /* _LINUX_UNITS_H */
|
|
diff --git include/net/af_unix.h include/net/af_unix.h
|
|
index 7ec1cdb66be8..e514508bdc92 100644
|
|
--- include/net/af_unix.h
|
|
+++ include/net/af_unix.h
|
|
@@ -43,12 +43,6 @@ struct unix_skb_parms {
|
|
|
|
#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb))
|
|
|
|
-#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
|
|
-#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
|
|
-#define unix_state_lock_nested(s) \
|
|
- spin_lock_nested(&unix_sk(s)->lock, \
|
|
- SINGLE_DEPTH_NESTING)
|
|
-
|
|
/* The AF_UNIX socket */
|
|
struct unix_sock {
|
|
/* WARNING: sk has to be the first member */
|
|
@@ -72,6 +66,20 @@ static inline struct unix_sock *unix_sk(const struct sock *sk)
|
|
return (struct unix_sock *)sk;
|
|
}
|
|
|
|
+#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
|
|
+#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
|
|
+enum unix_socket_lock_class {
|
|
+ U_LOCK_NORMAL,
|
|
+ U_LOCK_SECOND, /* for double locking, see unix_state_double_lock(). */
|
|
+ U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */
|
|
+};
|
|
+
|
|
+static inline void unix_state_lock_nested(struct sock *sk,
|
|
+ enum unix_socket_lock_class subclass)
|
|
+{
|
|
+ spin_lock_nested(&unix_sk(sk)->lock, subclass);
|
|
+}
|
|
+
|
|
#define peer_wait peer_wq.wait
|
|
|
|
long unix_inq_len(struct sock *sk);
|
|
diff --git include/net/bluetooth/hci_core.h include/net/bluetooth/hci_core.h
|
|
index 8f899ad4a754..bac3d79139b2 100644
|
|
--- include/net/bluetooth/hci_core.h
|
|
+++ include/net/bluetooth/hci_core.h
|
|
@@ -647,7 +647,6 @@ void hci_inquiry_cache_flush(struct hci_dev *hdev);
|
|
/* ----- HCI Connections ----- */
|
|
enum {
|
|
HCI_CONN_AUTH_PEND,
|
|
- HCI_CONN_REAUTH_PEND,
|
|
HCI_CONN_ENCRYPT_PEND,
|
|
HCI_CONN_RSWITCH_PEND,
|
|
HCI_CONN_MODE_CHANGE_PEND,
|
|
diff --git include/net/dst_ops.h include/net/dst_ops.h
|
|
index 443863c7b8da..632086b2f644 100644
|
|
--- include/net/dst_ops.h
|
|
+++ include/net/dst_ops.h
|
|
@@ -16,7 +16,7 @@ struct dst_ops {
|
|
unsigned short family;
|
|
unsigned int gc_thresh;
|
|
|
|
- int (*gc)(struct dst_ops *ops);
|
|
+ void (*gc)(struct dst_ops *ops);
|
|
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
|
|
unsigned int (*default_advmss)(const struct dst_entry *);
|
|
unsigned int (*mtu)(const struct dst_entry *);
|
|
@@ -53,9 +53,11 @@ static inline int dst_entries_get_slow(struct dst_ops *dst)
|
|
return percpu_counter_sum_positive(&dst->pcpuc_entries);
|
|
}
|
|
|
|
+#define DST_PERCPU_COUNTER_BATCH 32
|
|
static inline void dst_entries_add(struct dst_ops *dst, int val)
|
|
{
|
|
- percpu_counter_add(&dst->pcpuc_entries, val);
|
|
+ percpu_counter_add_batch(&dst->pcpuc_entries, val,
|
|
+ DST_PERCPU_COUNTER_BATCH);
|
|
}
|
|
|
|
static inline int dst_entries_init(struct dst_ops *dst)
|
|
diff --git include/net/llc_pdu.h include/net/llc_pdu.h
|
|
index 49aa79c7b278..581cd37aa98b 100644
|
|
--- include/net/llc_pdu.h
|
|
+++ include/net/llc_pdu.h
|
|
@@ -262,8 +262,7 @@ static inline void llc_pdu_header_init(struct sk_buff *skb, u8 type,
|
|
*/
|
|
static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
|
|
{
|
|
- if (skb->protocol == htons(ETH_P_802_2))
|
|
- memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
|
|
+ memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
|
|
}
|
|
|
|
/**
|
|
@@ -275,8 +274,7 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
|
|
*/
|
|
static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
|
|
{
|
|
- if (skb->protocol == htons(ETH_P_802_2))
|
|
- memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
|
|
+ memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
|
|
}
|
|
|
|
/**
|
|
diff --git include/net/netns/ipv6.h include/net/netns/ipv6.h
|
|
index c004d051c2d3..290ca18589ee 100644
|
|
--- include/net/netns/ipv6.h
|
|
+++ include/net/netns/ipv6.h
|
|
@@ -64,8 +64,8 @@ struct netns_ipv6 {
|
|
struct dst_ops ip6_dst_ops;
|
|
rwlock_t fib6_walker_lock;
|
|
spinlock_t fib6_gc_lock;
|
|
- unsigned int ip6_rt_gc_expire;
|
|
- unsigned long ip6_rt_last_gc;
|
|
+ atomic_t ip6_rt_gc_expire;
|
|
+ unsigned long ip6_rt_last_gc;
|
|
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
|
bool fib6_has_custom_rules;
|
|
struct rt6_info *ip6_prohibit_entry;
|
|
diff --git include/uapi/linux/btrfs.h include/uapi/linux/btrfs.h
|
|
index 86d2a52b4665..ee7a34c237a5 100644
|
|
--- include/uapi/linux/btrfs.h
|
|
+++ include/uapi/linux/btrfs.h
|
|
@@ -522,6 +522,9 @@ struct btrfs_ioctl_clone_range_args {
|
|
*/
|
|
#define BTRFS_DEFRAG_RANGE_COMPRESS 1
|
|
#define BTRFS_DEFRAG_RANGE_START_IO 2
|
|
+#define BTRFS_DEFRAG_RANGE_FLAGS_SUPP (BTRFS_DEFRAG_RANGE_COMPRESS | \
|
|
+ BTRFS_DEFRAG_RANGE_START_IO)
|
|
+
|
|
struct btrfs_ioctl_defrag_range_args {
|
|
/* start of the defrag operation */
|
|
__u64 start;
|
|
diff --git include/uapi/linux/netfilter/nf_tables.h include/uapi/linux/netfilter/nf_tables.h
|
|
index c7bb18ea4962..835e9f345f35 100644
|
|
--- include/uapi/linux/netfilter/nf_tables.h
|
|
+++ include/uapi/linux/netfilter/nf_tables.h
|
|
@@ -229,9 +229,11 @@ enum nft_rule_attributes {
|
|
/**
|
|
* enum nft_rule_compat_flags - nf_tables rule compat flags
|
|
*
|
|
+ * @NFT_RULE_COMPAT_F_UNUSED: unused
|
|
* @NFT_RULE_COMPAT_F_INV: invert the check result
|
|
*/
|
|
enum nft_rule_compat_flags {
|
|
+ NFT_RULE_COMPAT_F_UNUSED = (1 << 0),
|
|
NFT_RULE_COMPAT_F_INV = (1 << 1),
|
|
NFT_RULE_COMPAT_F_MASK = NFT_RULE_COMPAT_F_INV,
|
|
};
|
|
diff --git kernel/audit.c kernel/audit.c
|
|
index b694a265533f..819bdf0b6e5f 100644
|
|
--- kernel/audit.c
|
|
+++ kernel/audit.c
|
|
@@ -458,15 +458,19 @@ static int audit_set_failure(u32 state)
|
|
* @pid: auditd PID
|
|
* @portid: auditd netlink portid
|
|
* @net: auditd network namespace pointer
|
|
+ * @skb: the netlink command from the audit daemon
|
|
+ * @ack: netlink ack flag, cleared if ack'd here
|
|
*
|
|
* Description:
|
|
* This function will obtain and drop network namespace references as
|
|
* necessary. Returns zero on success, negative values on failure.
|
|
*/
|
|
-static int auditd_set(struct pid *pid, u32 portid, struct net *net)
|
|
+static int auditd_set(struct pid *pid, u32 portid, struct net *net,
|
|
+ struct sk_buff *skb, bool *ack)
|
|
{
|
|
unsigned long flags;
|
|
struct auditd_connection *ac_old, *ac_new;
|
|
+ struct nlmsghdr *nlh;
|
|
|
|
if (!pid || !net)
|
|
return -EINVAL;
|
|
@@ -478,6 +482,13 @@ static int auditd_set(struct pid *pid, u32 portid, struct net *net)
|
|
ac_new->portid = portid;
|
|
ac_new->net = get_net(net);
|
|
|
|
+ /* send the ack now to avoid a race with the queue backlog */
|
|
+ if (*ack) {
|
|
+ nlh = nlmsg_hdr(skb);
|
|
+ netlink_ack(skb, nlh, 0, NULL);
|
|
+ *ack = false;
|
|
+ }
|
|
+
|
|
spin_lock_irqsave(&auditd_conn_lock, flags);
|
|
ac_old = rcu_dereference_protected(auditd_conn,
|
|
lockdep_is_held(&auditd_conn_lock));
|
|
@@ -1165,7 +1176,8 @@ static int audit_replace(struct pid *pid)
|
|
return auditd_send_unicast_skb(skb);
|
|
}
|
|
|
|
-static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
+static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
+ bool *ack)
|
|
{
|
|
u32 seq;
|
|
void *data;
|
|
@@ -1257,7 +1269,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
/* register a new auditd connection */
|
|
err = auditd_set(req_pid,
|
|
NETLINK_CB(skb).portid,
|
|
- sock_net(NETLINK_CB(skb).sk));
|
|
+ sock_net(NETLINK_CB(skb).sk),
|
|
+ skb, ack);
|
|
if (audit_enabled != AUDIT_OFF)
|
|
audit_log_config_change("audit_pid",
|
|
new_pid,
|
|
@@ -1490,9 +1503,10 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
* Parse the provided skb and deal with any messages that may be present,
|
|
* malformed skbs are discarded.
|
|
*/
|
|
-static void audit_receive(struct sk_buff *skb)
|
|
+static void audit_receive(struct sk_buff *skb)
|
|
{
|
|
struct nlmsghdr *nlh;
|
|
+ bool ack;
|
|
/*
|
|
* len MUST be signed for nlmsg_next to be able to dec it below 0
|
|
* if the nlmsg_len was not aligned
|
|
@@ -1505,9 +1519,12 @@ static void audit_receive(struct sk_buff *skb)
|
|
|
|
mutex_lock(&audit_cmd_mutex);
|
|
while (nlmsg_ok(nlh, len)) {
|
|
- err = audit_receive_msg(skb, nlh);
|
|
- /* if err or if this message says it wants a response */
|
|
- if (err || (nlh->nlmsg_flags & NLM_F_ACK))
|
|
+ ack = nlh->nlmsg_flags & NLM_F_ACK;
|
|
+ err = audit_receive_msg(skb, nlh, &ack);
|
|
+
|
|
+ /* send an ack if the user asked for one and audit_receive_msg
|
|
+ * didn't already do it, or if there was an error. */
|
|
+ if (ack || err)
|
|
netlink_ack(skb, nlh, err, NULL);
|
|
|
|
nlh = nlmsg_next(nlh, &len);
|
|
diff --git kernel/bpf/arraymap.c kernel/bpf/arraymap.c
|
|
index a8f55ea4146b..3291c856cea9 100644
|
|
--- kernel/bpf/arraymap.c
|
|
+++ kernel/bpf/arraymap.c
|
|
@@ -416,7 +416,7 @@ int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file,
|
|
|
|
old_ptr = xchg(array->ptrs + index, new_ptr);
|
|
if (old_ptr)
|
|
- map->ops->map_fd_put_ptr(old_ptr);
|
|
+ map->ops->map_fd_put_ptr(map, old_ptr, true);
|
|
|
|
return 0;
|
|
}
|
|
@@ -432,7 +432,7 @@ static int fd_array_map_delete_elem(struct bpf_map *map, void *key)
|
|
|
|
old_ptr = xchg(array->ptrs + index, NULL);
|
|
if (old_ptr) {
|
|
- map->ops->map_fd_put_ptr(old_ptr);
|
|
+ map->ops->map_fd_put_ptr(map, old_ptr, true);
|
|
return 0;
|
|
} else {
|
|
return -ENOENT;
|
|
@@ -456,8 +456,9 @@ static void *prog_fd_array_get_ptr(struct bpf_map *map,
|
|
return prog;
|
|
}
|
|
|
|
-static void prog_fd_array_put_ptr(void *ptr)
|
|
+static void prog_fd_array_put_ptr(struct bpf_map *map, void *ptr, bool need_defer)
|
|
{
|
|
+ /* bpf_prog is freed after one RCU or tasks trace grace period */
|
|
bpf_prog_put(ptr);
|
|
}
|
|
|
|
@@ -543,8 +544,9 @@ err_out:
|
|
return ee;
|
|
}
|
|
|
|
-static void perf_event_fd_array_put_ptr(void *ptr)
|
|
+static void perf_event_fd_array_put_ptr(struct bpf_map *map, void *ptr, bool need_defer)
|
|
{
|
|
+ /* bpf_perf_event is freed after one RCU grace period */
|
|
bpf_event_entry_free_rcu(ptr);
|
|
}
|
|
|
|
@@ -583,7 +585,7 @@ static void *cgroup_fd_array_get_ptr(struct bpf_map *map,
|
|
return cgroup_get_from_fd(fd);
|
|
}
|
|
|
|
-static void cgroup_fd_array_put_ptr(void *ptr)
|
|
+static void cgroup_fd_array_put_ptr(struct bpf_map *map, void *ptr, bool need_defer)
|
|
{
|
|
/* cgroup_put free cgrp after a rcu grace period */
|
|
cgroup_put(ptr);
|
|
diff --git kernel/bpf/hashtab.c kernel/bpf/hashtab.c
|
|
index ecc58137525b..db2c3e019daf 100644
|
|
--- kernel/bpf/hashtab.c
|
|
+++ kernel/bpf/hashtab.c
|
|
@@ -655,7 +655,7 @@ static void htab_put_fd_value(struct bpf_htab *htab, struct htab_elem *l)
|
|
|
|
if (map->ops->map_fd_put_ptr) {
|
|
ptr = fd_htab_map_get_ptr(map, l);
|
|
- map->ops->map_fd_put_ptr(ptr);
|
|
+ map->ops->map_fd_put_ptr(map, ptr, true);
|
|
}
|
|
}
|
|
|
|
@@ -1288,7 +1288,7 @@ static void fd_htab_map_free(struct bpf_map *map)
|
|
hlist_nulls_for_each_entry_safe(l, n, head, hash_node) {
|
|
void *ptr = fd_htab_map_get_ptr(map, l);
|
|
|
|
- map->ops->map_fd_put_ptr(ptr);
|
|
+ map->ops->map_fd_put_ptr(map, ptr, false);
|
|
}
|
|
}
|
|
|
|
@@ -1329,7 +1329,7 @@ int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file,
|
|
|
|
ret = htab_map_update_elem(map, key, &ptr, map_flags);
|
|
if (ret)
|
|
- map->ops->map_fd_put_ptr(ptr);
|
|
+ map->ops->map_fd_put_ptr(map, ptr, false);
|
|
|
|
return ret;
|
|
}
|
|
diff --git kernel/bpf/lpm_trie.c kernel/bpf/lpm_trie.c
|
|
index c28c584b734e..ef324c9c1eca 100644
|
|
--- kernel/bpf/lpm_trie.c
|
|
+++ kernel/bpf/lpm_trie.c
|
|
@@ -192,6 +192,9 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key)
|
|
struct lpm_trie_node *node, *found = NULL;
|
|
struct bpf_lpm_trie_key *key = _key;
|
|
|
|
+ if (key->prefixlen > trie->max_prefixlen)
|
|
+ return NULL;
|
|
+
|
|
/* Start walking the trie from the root node ... */
|
|
|
|
for (node = rcu_dereference(trie->root); node;) {
|
|
diff --git kernel/bpf/map_in_map.c kernel/bpf/map_in_map.c
|
|
index c0c494b7647b..1878aace6a5c 100644
|
|
--- kernel/bpf/map_in_map.c
|
|
+++ kernel/bpf/map_in_map.c
|
|
@@ -101,7 +101,7 @@ void *bpf_map_fd_get_ptr(struct bpf_map *map,
|
|
return inner_map;
|
|
}
|
|
|
|
-void bpf_map_fd_put_ptr(void *ptr)
|
|
+void bpf_map_fd_put_ptr(struct bpf_map *map, void *ptr, bool need_defer)
|
|
{
|
|
/* ptr->ops->map_free() has to go through one
|
|
* rcu grace period by itself.
|
|
diff --git kernel/bpf/map_in_map.h kernel/bpf/map_in_map.h
|
|
index 6183db9ec08c..1e652a7bf60e 100644
|
|
--- kernel/bpf/map_in_map.h
|
|
+++ kernel/bpf/map_in_map.h
|
|
@@ -18,7 +18,7 @@ bool bpf_map_meta_equal(const struct bpf_map *meta0,
|
|
const struct bpf_map *meta1);
|
|
void *bpf_map_fd_get_ptr(struct bpf_map *map, struct file *map_file,
|
|
int ufd);
|
|
-void bpf_map_fd_put_ptr(void *ptr);
|
|
+void bpf_map_fd_put_ptr(struct bpf_map *map, void *ptr, bool need_defer);
|
|
u32 bpf_map_fd_sys_lookup_elem(void *ptr);
|
|
|
|
#endif
|
|
diff --git kernel/debug/kdb/kdb_main.c kernel/debug/kdb/kdb_main.c
|
|
index 15d902daeef6..01a4312ede49 100644
|
|
--- kernel/debug/kdb/kdb_main.c
|
|
+++ kernel/debug/kdb/kdb_main.c
|
|
@@ -399,6 +399,13 @@ int kdb_set(int argc, const char **argv)
|
|
if (argc != 2)
|
|
return KDB_ARGCOUNT;
|
|
|
|
+ /*
|
|
+ * Censor sensitive variables
|
|
+ */
|
|
+ if (strcmp(argv[1], "PROMPT") == 0 &&
|
|
+ !kdb_check_flags(KDB_ENABLE_MEM_READ, kdb_cmd_enabled, false))
|
|
+ return KDB_NOPERM;
|
|
+
|
|
/*
|
|
* Check for internal variables
|
|
*/
|
|
@@ -1289,14 +1296,9 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
|
|
*(cmd_hist[cmd_head]) = '\0';
|
|
|
|
do_full_getstr:
|
|
-#if defined(CONFIG_SMP)
|
|
+ /* PROMPT can only be set if we have MEM_READ permission. */
|
|
snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"),
|
|
raw_smp_processor_id());
|
|
-#else
|
|
- snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"));
|
|
-#endif
|
|
- if (defcmd_in_progress)
|
|
- strncat(kdb_prompt_str, "[defcmd]", CMD_BUFLEN);
|
|
|
|
/*
|
|
* Fetch command from keyboard
|
|
diff --git kernel/power/swap.c kernel/power/swap.c
|
|
index 8b37085a6690..b62a56de91d6 100644
|
|
--- kernel/power/swap.c
|
|
+++ kernel/power/swap.c
|
|
@@ -595,11 +595,11 @@ static int crc32_threadfn(void *data)
|
|
unsigned i;
|
|
|
|
while (1) {
|
|
- wait_event(d->go, atomic_read(&d->ready) ||
|
|
+ wait_event(d->go, atomic_read_acquire(&d->ready) ||
|
|
kthread_should_stop());
|
|
if (kthread_should_stop()) {
|
|
d->thr = NULL;
|
|
- atomic_set(&d->stop, 1);
|
|
+ atomic_set_release(&d->stop, 1);
|
|
wake_up(&d->done);
|
|
break;
|
|
}
|
|
@@ -608,7 +608,7 @@ static int crc32_threadfn(void *data)
|
|
for (i = 0; i < d->run_threads; i++)
|
|
*d->crc32 = crc32_le(*d->crc32,
|
|
d->unc[i], *d->unc_len[i]);
|
|
- atomic_set(&d->stop, 1);
|
|
+ atomic_set_release(&d->stop, 1);
|
|
wake_up(&d->done);
|
|
}
|
|
return 0;
|
|
@@ -638,12 +638,12 @@ static int lzo_compress_threadfn(void *data)
|
|
struct cmp_data *d = data;
|
|
|
|
while (1) {
|
|
- wait_event(d->go, atomic_read(&d->ready) ||
|
|
+ wait_event(d->go, atomic_read_acquire(&d->ready) ||
|
|
kthread_should_stop());
|
|
if (kthread_should_stop()) {
|
|
d->thr = NULL;
|
|
d->ret = -1;
|
|
- atomic_set(&d->stop, 1);
|
|
+ atomic_set_release(&d->stop, 1);
|
|
wake_up(&d->done);
|
|
break;
|
|
}
|
|
@@ -652,7 +652,7 @@ static int lzo_compress_threadfn(void *data)
|
|
d->ret = lzo1x_1_compress(d->unc, d->unc_len,
|
|
d->cmp + LZO_HEADER, &d->cmp_len,
|
|
d->wrk);
|
|
- atomic_set(&d->stop, 1);
|
|
+ atomic_set_release(&d->stop, 1);
|
|
wake_up(&d->done);
|
|
}
|
|
return 0;
|
|
@@ -794,7 +794,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
|
|
|
|
data[thr].unc_len = off;
|
|
|
|
- atomic_set(&data[thr].ready, 1);
|
|
+ atomic_set_release(&data[thr].ready, 1);
|
|
wake_up(&data[thr].go);
|
|
}
|
|
|
|
@@ -802,12 +802,12 @@ static int save_image_lzo(struct swap_map_handle *handle,
|
|
break;
|
|
|
|
crc->run_threads = thr;
|
|
- atomic_set(&crc->ready, 1);
|
|
+ atomic_set_release(&crc->ready, 1);
|
|
wake_up(&crc->go);
|
|
|
|
for (run_threads = thr, thr = 0; thr < run_threads; thr++) {
|
|
wait_event(data[thr].done,
|
|
- atomic_read(&data[thr].stop));
|
|
+ atomic_read_acquire(&data[thr].stop));
|
|
atomic_set(&data[thr].stop, 0);
|
|
|
|
ret = data[thr].ret;
|
|
@@ -847,7 +847,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
|
|
}
|
|
}
|
|
|
|
- wait_event(crc->done, atomic_read(&crc->stop));
|
|
+ wait_event(crc->done, atomic_read_acquire(&crc->stop));
|
|
atomic_set(&crc->stop, 0);
|
|
}
|
|
|
|
@@ -1129,12 +1129,12 @@ static int lzo_decompress_threadfn(void *data)
|
|
struct dec_data *d = data;
|
|
|
|
while (1) {
|
|
- wait_event(d->go, atomic_read(&d->ready) ||
|
|
+ wait_event(d->go, atomic_read_acquire(&d->ready) ||
|
|
kthread_should_stop());
|
|
if (kthread_should_stop()) {
|
|
d->thr = NULL;
|
|
d->ret = -1;
|
|
- atomic_set(&d->stop, 1);
|
|
+ atomic_set_release(&d->stop, 1);
|
|
wake_up(&d->done);
|
|
break;
|
|
}
|
|
@@ -1147,7 +1147,7 @@ static int lzo_decompress_threadfn(void *data)
|
|
flush_icache_range((unsigned long)d->unc,
|
|
(unsigned long)d->unc + d->unc_len);
|
|
|
|
- atomic_set(&d->stop, 1);
|
|
+ atomic_set_release(&d->stop, 1);
|
|
wake_up(&d->done);
|
|
}
|
|
return 0;
|
|
@@ -1338,7 +1338,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
|
}
|
|
|
|
if (crc->run_threads) {
|
|
- wait_event(crc->done, atomic_read(&crc->stop));
|
|
+ wait_event(crc->done, atomic_read_acquire(&crc->stop));
|
|
atomic_set(&crc->stop, 0);
|
|
crc->run_threads = 0;
|
|
}
|
|
@@ -1375,7 +1375,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
|
pg = 0;
|
|
}
|
|
|
|
- atomic_set(&data[thr].ready, 1);
|
|
+ atomic_set_release(&data[thr].ready, 1);
|
|
wake_up(&data[thr].go);
|
|
}
|
|
|
|
@@ -1394,7 +1394,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
|
|
|
for (run_threads = thr, thr = 0; thr < run_threads; thr++) {
|
|
wait_event(data[thr].done,
|
|
- atomic_read(&data[thr].stop));
|
|
+ atomic_read_acquire(&data[thr].stop));
|
|
atomic_set(&data[thr].stop, 0);
|
|
|
|
ret = data[thr].ret;
|
|
@@ -1429,7 +1429,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
|
ret = snapshot_write_next(snapshot);
|
|
if (ret <= 0) {
|
|
crc->run_threads = thr + 1;
|
|
- atomic_set(&crc->ready, 1);
|
|
+ atomic_set_release(&crc->ready, 1);
|
|
wake_up(&crc->go);
|
|
goto out_finish;
|
|
}
|
|
@@ -1437,13 +1437,13 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
|
}
|
|
|
|
crc->run_threads = thr;
|
|
- atomic_set(&crc->ready, 1);
|
|
+ atomic_set_release(&crc->ready, 1);
|
|
wake_up(&crc->go);
|
|
}
|
|
|
|
out_finish:
|
|
if (crc->run_threads) {
|
|
- wait_event(crc->done, atomic_read(&crc->stop));
|
|
+ wait_event(crc->done, atomic_read_acquire(&crc->stop));
|
|
atomic_set(&crc->stop, 0);
|
|
}
|
|
stop = ktime_get();
|
|
diff --git kernel/sched/membarrier.c kernel/sched/membarrier.c
|
|
index 9bcbacba82a8..d936a130814e 100644
|
|
--- kernel/sched/membarrier.c
|
|
+++ kernel/sched/membarrier.c
|
|
@@ -30,6 +30,8 @@
|
|
(MEMBARRIER_CMD_SHARED | MEMBARRIER_CMD_PRIVATE_EXPEDITED \
|
|
| MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED)
|
|
|
|
+static DEFINE_MUTEX(membarrier_ipi_mutex);
|
|
+
|
|
static void ipi_mb(void *info)
|
|
{
|
|
smp_mb(); /* IPIs should be serializing but paranoid. */
|
|
@@ -64,6 +66,7 @@ static int membarrier_private_expedited(void)
|
|
fallback = true;
|
|
}
|
|
|
|
+ mutex_lock(&membarrier_ipi_mutex);
|
|
cpus_read_lock();
|
|
for_each_online_cpu(cpu) {
|
|
struct task_struct *p;
|
|
@@ -102,6 +105,7 @@ static int membarrier_private_expedited(void)
|
|
* rq->curr modification in scheduler.
|
|
*/
|
|
smp_mb(); /* exit from system call is not a mb */
|
|
+ mutex_unlock(&membarrier_ipi_mutex);
|
|
return 0;
|
|
}
|
|
|
|
diff --git kernel/sched/rt.c kernel/sched/rt.c
|
|
index c093bb0f52eb..85cc7ab4f38d 100644
|
|
--- kernel/sched/rt.c
|
|
+++ kernel/sched/rt.c
|
|
@@ -10,7 +10,7 @@
|
|
#include <linux/irq_work.h>
|
|
|
|
int sched_rr_timeslice = RR_TIMESLICE;
|
|
-int sysctl_sched_rr_timeslice = (MSEC_PER_SEC / HZ) * RR_TIMESLICE;
|
|
+int sysctl_sched_rr_timeslice = (MSEC_PER_SEC * RR_TIMESLICE) / HZ;
|
|
|
|
static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun);
|
|
|
|
@@ -2626,9 +2626,6 @@ static int sched_rt_global_constraints(void)
|
|
|
|
static int sched_rt_global_validate(void)
|
|
{
|
|
- if (sysctl_sched_rt_period <= 0)
|
|
- return -EINVAL;
|
|
-
|
|
if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
|
|
(sysctl_sched_rt_runtime > sysctl_sched_rt_period))
|
|
return -EINVAL;
|
|
@@ -2658,7 +2655,7 @@ int sched_rt_handler(struct ctl_table *table, int write,
|
|
old_period = sysctl_sched_rt_period;
|
|
old_runtime = sysctl_sched_rt_runtime;
|
|
|
|
- ret = proc_dointvec(table, write, buffer, lenp, ppos);
|
|
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
|
|
|
if (!ret && write) {
|
|
ret = sched_rt_global_validate();
|
|
@@ -2703,6 +2700,9 @@ int sched_rr_handler(struct ctl_table *table, int write,
|
|
sched_rr_timeslice =
|
|
sysctl_sched_rr_timeslice <= 0 ? RR_TIMESLICE :
|
|
msecs_to_jiffies(sysctl_sched_rr_timeslice);
|
|
+
|
|
+ if (sysctl_sched_rr_timeslice <= 0)
|
|
+ sysctl_sched_rr_timeslice = jiffies_to_msecs(RR_TIMESLICE);
|
|
}
|
|
mutex_unlock(&mutex);
|
|
return ret;
|
|
diff --git kernel/sysctl.c kernel/sysctl.c
|
|
index de4a197570b1..5bee2eb28ff6 100644
|
|
--- kernel/sysctl.c
|
|
+++ kernel/sysctl.c
|
|
@@ -124,6 +124,7 @@ static int zero;
|
|
static int __maybe_unused one = 1;
|
|
static int __maybe_unused two = 2;
|
|
static int __maybe_unused four = 4;
|
|
+static int int_max = INT_MAX;
|
|
static unsigned long zero_ul;
|
|
static unsigned long one_ul = 1;
|
|
static unsigned long long_max = LONG_MAX;
|
|
@@ -460,6 +461,8 @@ static struct ctl_table kern_table[] = {
|
|
.maxlen = sizeof(unsigned int),
|
|
.mode = 0644,
|
|
.proc_handler = sched_rt_handler,
|
|
+ .extra1 = &one,
|
|
+ .extra2 = &int_max,
|
|
},
|
|
{
|
|
.procname = "sched_rt_runtime_us",
|
|
@@ -467,6 +470,8 @@ static struct ctl_table kern_table[] = {
|
|
.maxlen = sizeof(int),
|
|
.mode = 0644,
|
|
.proc_handler = sched_rt_handler,
|
|
+ .extra1 = &neg_one,
|
|
+ .extra2 = &int_max,
|
|
},
|
|
{
|
|
.procname = "sched_rr_timeslice_ms",
|
|
diff --git kernel/time/tick-sched.c kernel/time/tick-sched.c
|
|
index 3c7b400512eb..387de1b6dd93 100644
|
|
--- kernel/time/tick-sched.c
|
|
+++ kernel/time/tick-sched.c
|
|
@@ -1278,13 +1278,23 @@ void tick_setup_sched_timer(void)
|
|
void tick_cancel_sched_timer(int cpu)
|
|
{
|
|
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
|
|
+ ktime_t idle_sleeptime, iowait_sleeptime;
|
|
+ unsigned long idle_calls, idle_sleeps;
|
|
|
|
# ifdef CONFIG_HIGH_RES_TIMERS
|
|
if (ts->sched_timer.base)
|
|
hrtimer_cancel(&ts->sched_timer);
|
|
# endif
|
|
|
|
+ idle_sleeptime = ts->idle_sleeptime;
|
|
+ iowait_sleeptime = ts->iowait_sleeptime;
|
|
+ idle_calls = ts->idle_calls;
|
|
+ idle_sleeps = ts->idle_sleeps;
|
|
memset(ts, 0, sizeof(*ts));
|
|
+ ts->idle_sleeptime = idle_sleeptime;
|
|
+ ts->iowait_sleeptime = iowait_sleeptime;
|
|
+ ts->idle_calls = idle_calls;
|
|
+ ts->idle_sleeps = idle_sleeps;
|
|
}
|
|
#endif
|
|
|
|
diff --git kernel/trace/ring_buffer.c kernel/trace/ring_buffer.c
|
|
index 3fc09d765f2a..8c09e8ca1561 100644
|
|
--- kernel/trace/ring_buffer.c
|
|
+++ kernel/trace/ring_buffer.c
|
|
@@ -2776,6 +2776,12 @@ rb_reserve_next_event(struct ring_buffer *buffer,
|
|
int nr_loops = 0;
|
|
u64 diff;
|
|
|
|
+ /* ring buffer does cmpxchg, make sure it is safe in NMI context */
|
|
+ if (!IS_ENABLED(CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG) &&
|
|
+ (unlikely(in_nmi()))) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
rb_start_commit(cpu_buffer);
|
|
|
|
#ifdef CONFIG_RING_BUFFER_ALLOW_SWAP
|
|
diff --git kernel/trace/trace.c kernel/trace/trace.c
|
|
index c5fe020336be..755d6146c738 100644
|
|
--- kernel/trace/trace.c
|
|
+++ kernel/trace/trace.c
|
|
@@ -3826,7 +3826,11 @@ static int s_show(struct seq_file *m, void *v)
|
|
iter->leftover = ret;
|
|
|
|
} else {
|
|
- print_trace_line(iter);
|
|
+ ret = print_trace_line(iter);
|
|
+ if (ret == TRACE_TYPE_PARTIAL_LINE) {
|
|
+ iter->seq.full = 0;
|
|
+ trace_seq_puts(&iter->seq, "[LINE TOO BIG]\n");
|
|
+ }
|
|
ret = trace_print_seq(m, &iter->seq);
|
|
/*
|
|
* If we overflow the seq_file buffer, then it will
|
|
diff --git kernel/trace/trace_events_trigger.c kernel/trace/trace_events_trigger.c
|
|
index 40c1a2dd48f0..871ea0fa78bb 100644
|
|
--- kernel/trace/trace_events_trigger.c
|
|
+++ kernel/trace/trace_events_trigger.c
|
|
@@ -1127,8 +1127,10 @@ register_snapshot_trigger(char *glob, struct event_trigger_ops *ops,
|
|
struct event_trigger_data *data,
|
|
struct trace_event_file *file)
|
|
{
|
|
- if (tracing_alloc_snapshot_instance(file->tr) != 0)
|
|
- return 0;
|
|
+ int ret = tracing_alloc_snapshot_instance(file->tr);
|
|
+
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
return register_trigger(glob, ops, data, file);
|
|
}
|
|
diff --git kernel/trace/trace_output.c kernel/trace/trace_output.c
|
|
index e3ab66e6fd85..3ca9ddfef2b8 100644
|
|
--- kernel/trace/trace_output.c
|
|
+++ kernel/trace/trace_output.c
|
|
@@ -1319,11 +1319,12 @@ static enum print_line_t trace_print_print(struct trace_iterator *iter,
|
|
{
|
|
struct print_entry *field;
|
|
struct trace_seq *s = &iter->seq;
|
|
+ int max = iter->ent_size - offsetof(struct print_entry, buf);
|
|
|
|
trace_assign_type(field, iter->ent);
|
|
|
|
seq_print_ip_sym(s, field->ip, flags);
|
|
- trace_seq_printf(s, ": %s", field->buf);
|
|
+ trace_seq_printf(s, ": %.*s", max, field->buf);
|
|
|
|
return trace_handle_return(s);
|
|
}
|
|
@@ -1332,10 +1333,11 @@ static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags,
|
|
struct trace_event *event)
|
|
{
|
|
struct print_entry *field;
|
|
+ int max = iter->ent_size - offsetof(struct print_entry, buf);
|
|
|
|
trace_assign_type(field, iter->ent);
|
|
|
|
- trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf);
|
|
+ trace_seq_printf(&iter->seq, "# %lx %.*s", field->ip, max, field->buf);
|
|
|
|
return trace_handle_return(&iter->seq);
|
|
}
|
|
diff --git mm/memcontrol.c mm/memcontrol.c
|
|
index 22d13c98e274..e6a351e69ac3 100644
|
|
--- mm/memcontrol.c
|
|
+++ mm/memcontrol.c
|
|
@@ -1747,6 +1747,9 @@ static void drain_stock(struct memcg_stock_pcp *stock)
|
|
{
|
|
struct mem_cgroup *old = stock->cached;
|
|
|
|
+ if (!old)
|
|
+ return;
|
|
+
|
|
if (stock->nr_pages) {
|
|
page_counter_uncharge(&old->memory, stock->nr_pages);
|
|
if (do_memsw_account())
|
|
@@ -1754,6 +1757,8 @@ static void drain_stock(struct memcg_stock_pcp *stock)
|
|
css_put_many(&old->css, stock->nr_pages);
|
|
stock->nr_pages = 0;
|
|
}
|
|
+
|
|
+ css_put(&old->css);
|
|
stock->cached = NULL;
|
|
}
|
|
|
|
@@ -1789,6 +1794,7 @@ static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
|
|
stock = this_cpu_ptr(&memcg_stock);
|
|
if (stock->cached != memcg) { /* reset if necessary */
|
|
drain_stock(stock);
|
|
+ css_get(&memcg->css);
|
|
stock->cached = memcg;
|
|
}
|
|
stock->nr_pages += nr_pages;
|
|
@@ -1820,21 +1826,22 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
|
|
for_each_online_cpu(cpu) {
|
|
struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
|
|
struct mem_cgroup *memcg;
|
|
+ bool flush = false;
|
|
|
|
+ rcu_read_lock();
|
|
memcg = stock->cached;
|
|
- if (!memcg || !stock->nr_pages || !css_tryget(&memcg->css))
|
|
- continue;
|
|
- if (!mem_cgroup_is_descendant(memcg, root_memcg)) {
|
|
- css_put(&memcg->css);
|
|
- continue;
|
|
- }
|
|
- if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
|
|
+ if (memcg && stock->nr_pages &&
|
|
+ mem_cgroup_is_descendant(memcg, root_memcg))
|
|
+ flush = true;
|
|
+ rcu_read_unlock();
|
|
+
|
|
+ if (flush &&
|
|
+ !test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
|
|
if (cpu == curcpu)
|
|
drain_local_stock(&stock->work);
|
|
else
|
|
schedule_work_on(cpu, &stock->work);
|
|
}
|
|
- css_put(&memcg->css);
|
|
}
|
|
put_cpu();
|
|
mutex_unlock(&percpu_charge_mutex);
|
|
diff --git mm/memory-failure.c mm/memory-failure.c
|
|
index e7827b9e6397..e179ffa15026 100644
|
|
--- mm/memory-failure.c
|
|
+++ mm/memory-failure.c
|
|
@@ -952,7 +952,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
|
|
* This check implies we don't kill processes if their pages
|
|
* are in the swap cache early. Those are always late kills.
|
|
*/
|
|
- if (!page_mapped(hpage))
|
|
+ if (!page_mapped(p))
|
|
return true;
|
|
|
|
if (PageKsm(p)) {
|
|
@@ -996,10 +996,10 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
|
|
if (kill)
|
|
collect_procs(hpage, &tokill, flags & MF_ACTION_REQUIRED);
|
|
|
|
- unmap_success = try_to_unmap(hpage, ttu);
|
|
+ unmap_success = try_to_unmap(p, ttu);
|
|
if (!unmap_success)
|
|
pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n",
|
|
- pfn, page_mapcount(hpage));
|
|
+ pfn, page_mapcount(p));
|
|
|
|
/*
|
|
* try_to_unmap() might put mlocked page in lru cache, so call
|
|
diff --git mm/memory.c mm/memory.c
|
|
index 0136af15ba18..aa0c46997ce8 100644
|
|
--- mm/memory.c
|
|
+++ mm/memory.c
|
|
@@ -2958,8 +2958,8 @@ void unmap_mapping_range(struct address_space *mapping,
|
|
loff_t const holebegin, loff_t const holelen, int even_cows)
|
|
{
|
|
struct zap_details details = { };
|
|
- pgoff_t hba = holebegin >> PAGE_SHIFT;
|
|
- pgoff_t hlen = (holelen + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
+ pgoff_t hba = (pgoff_t)(holebegin) >> PAGE_SHIFT;
|
|
+ pgoff_t hlen = ((pgoff_t)(holelen) + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
|
|
/* Check for overflow. */
|
|
if (sizeof(holelen) > sizeof(hlen)) {
|
|
diff --git mm/page-writeback.c mm/page-writeback.c
|
|
index 29f9980c13ac..2193086847b3 100644
|
|
--- mm/page-writeback.c
|
|
+++ mm/page-writeback.c
|
|
@@ -1531,7 +1531,7 @@ static inline void wb_dirty_limits(struct dirty_throttle_control *dtc)
|
|
*/
|
|
dtc->wb_thresh = __wb_calc_thresh(dtc);
|
|
dtc->wb_bg_thresh = dtc->thresh ?
|
|
- div_u64((u64)dtc->wb_thresh * dtc->bg_thresh, dtc->thresh) : 0;
|
|
+ div64_u64(dtc->wb_thresh * dtc->bg_thresh, dtc->thresh) : 0;
|
|
|
|
/*
|
|
* In order to avoid the stacked BDI deadlock we need
|
|
diff --git net/8021q/vlan_netlink.c net/8021q/vlan_netlink.c
|
|
index fdf39dd5e755..aad09715ac49 100644
|
|
--- net/8021q/vlan_netlink.c
|
|
+++ net/8021q/vlan_netlink.c
|
|
@@ -105,12 +105,16 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
}
|
|
if (data[IFLA_VLAN_INGRESS_QOS]) {
|
|
nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
|
|
+ if (nla_type(attr) != IFLA_VLAN_QOS_MAPPING)
|
|
+ continue;
|
|
m = nla_data(attr);
|
|
vlan_dev_set_ingress_priority(dev, m->to, m->from);
|
|
}
|
|
}
|
|
if (data[IFLA_VLAN_EGRESS_QOS]) {
|
|
nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
|
|
+ if (nla_type(attr) != IFLA_VLAN_QOS_MAPPING)
|
|
+ continue;
|
|
m = nla_data(attr);
|
|
err = vlan_dev_set_egress_priority(dev, m->from, m->to);
|
|
if (err)
|
|
diff --git net/bluetooth/hci_conn.c net/bluetooth/hci_conn.c
|
|
index ce4bbc426946..017abffccc15 100644
|
|
--- net/bluetooth/hci_conn.c
|
|
+++ net/bluetooth/hci_conn.c
|
|
@@ -1221,12 +1221,10 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
|
|
hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
|
|
sizeof(cp), &cp);
|
|
|
|
- /* If we're already encrypted set the REAUTH_PEND flag,
|
|
- * otherwise set the ENCRYPT_PEND.
|
|
+ /* Set the ENCRYPT_PEND to trigger encryption after
|
|
+ * authentication.
|
|
*/
|
|
- if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
|
- set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
|
|
- else
|
|
+ if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
|
set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
|
}
|
|
|
|
diff --git net/bluetooth/hci_core.c net/bluetooth/hci_core.c
|
|
index 2bf0bdee7186..8faecd94bf5a 100644
|
|
--- net/bluetooth/hci_core.c
|
|
+++ net/bluetooth/hci_core.c
|
|
@@ -2167,6 +2167,7 @@ static void hci_error_reset(struct work_struct *work)
|
|
{
|
|
struct hci_dev *hdev = container_of(work, struct hci_dev, error_reset);
|
|
|
|
+ hci_dev_hold(hdev);
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
if (hdev->hw_error)
|
|
@@ -2175,10 +2176,10 @@ static void hci_error_reset(struct work_struct *work)
|
|
BT_ERR("%s hardware error 0x%2.2x", hdev->name,
|
|
hdev->hw_error_code);
|
|
|
|
- if (hci_dev_do_close(hdev))
|
|
- return;
|
|
+ if (!hci_dev_do_close(hdev))
|
|
+ hci_dev_do_open(hdev);
|
|
|
|
- hci_dev_do_open(hdev);
|
|
+ hci_dev_put(hdev);
|
|
}
|
|
|
|
void hci_uuids_clear(struct hci_dev *hdev)
|
|
diff --git net/bluetooth/hci_event.c net/bluetooth/hci_event.c
|
|
index 07605fcc9091..987ba33375c9 100644
|
|
--- net/bluetooth/hci_event.c
|
|
+++ net/bluetooth/hci_event.c
|
|
@@ -2459,14 +2459,8 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
if (!ev->status) {
|
|
clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
|
-
|
|
- if (!hci_conn_ssp_enabled(conn) &&
|
|
- test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
|
|
- BT_INFO("re-auth of legacy device is not possible.");
|
|
- } else {
|
|
- set_bit(HCI_CONN_AUTH, &conn->flags);
|
|
- conn->sec_level = conn->pending_sec_level;
|
|
- }
|
|
+ set_bit(HCI_CONN_AUTH, &conn->flags);
|
|
+ conn->sec_level = conn->pending_sec_level;
|
|
} else {
|
|
if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
|
|
set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
|
@@ -2475,7 +2469,6 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|
}
|
|
|
|
clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
|
|
- clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
|
|
|
|
if (conn->state == BT_CONFIG) {
|
|
if (!ev->status && hci_conn_ssp_enabled(conn)) {
|
|
@@ -4022,9 +4015,12 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|
hci_dev_lock(hdev);
|
|
|
|
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
|
|
- if (!conn || !hci_conn_ssp_enabled(conn))
|
|
+ if (!conn || !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
|
|
goto unlock;
|
|
|
|
+ /* Assume remote supports SSP since it has triggered this event */
|
|
+ set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
|
|
+
|
|
hci_conn_hold(conn);
|
|
|
|
if (!hci_dev_test_flag(hdev, HCI_MGMT))
|
|
@@ -5148,6 +5144,10 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
|
|
return send_conn_param_neg_reply(hdev, handle,
|
|
HCI_ERROR_UNKNOWN_CONN_ID);
|
|
|
|
+ if (max > hcon->le_conn_max_interval)
|
|
+ return send_conn_param_neg_reply(hdev, handle,
|
|
+ HCI_ERROR_INVALID_LL_PARAMS);
|
|
+
|
|
if (hci_check_conn_params(min, max, latency, timeout))
|
|
return send_conn_param_neg_reply(hdev, handle,
|
|
HCI_ERROR_INVALID_LL_PARAMS);
|
|
diff --git net/bluetooth/l2cap_core.c net/bluetooth/l2cap_core.c
|
|
index 6bae68b5d439..e52657f05f78 100644
|
|
--- net/bluetooth/l2cap_core.c
|
|
+++ net/bluetooth/l2cap_core.c
|
|
@@ -5313,7 +5313,13 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
|
|
|
|
memset(&rsp, 0, sizeof(rsp));
|
|
|
|
- err = hci_check_conn_params(min, max, latency, to_multiplier);
|
|
+ if (max > hcon->le_conn_max_interval) {
|
|
+ BT_DBG("requested connection interval exceeds current bounds.");
|
|
+ err = -EINVAL;
|
|
+ } else {
|
|
+ err = hci_check_conn_params(min, max, latency, to_multiplier);
|
|
+ }
|
|
+
|
|
if (err)
|
|
rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
|
|
else
|
|
diff --git net/core/dst.c net/core/dst.c
|
|
index a6c47da7d0f8..2d121958d5b0 100644
|
|
--- net/core/dst.c
|
|
+++ net/core/dst.c
|
|
@@ -99,10 +99,10 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
|
|
{
|
|
struct dst_entry *dst;
|
|
|
|
- if (ops->gc && dst_entries_get_fast(ops) > ops->gc_thresh) {
|
|
- if (ops->gc(ops))
|
|
- return NULL;
|
|
- }
|
|
+ if (ops->gc &&
|
|
+ !(flags & DST_NOCOUNT) &&
|
|
+ dst_entries_get_fast(ops) > ops->gc_thresh)
|
|
+ ops->gc(ops);
|
|
|
|
dst = kmem_cache_alloc(ops->kmem_cachep, GFP_ATOMIC);
|
|
if (!dst)
|
|
diff --git net/ipv4/af_inet.c net/ipv4/af_inet.c
|
|
index 1eee002b12d2..5feb84c43564 100644
|
|
--- net/ipv4/af_inet.c
|
|
+++ net/ipv4/af_inet.c
|
|
@@ -1480,10 +1480,12 @@ EXPORT_SYMBOL(inet_current_timestamp);
|
|
|
|
int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
|
{
|
|
- if (sk->sk_family == AF_INET)
|
|
+ unsigned int family = READ_ONCE(sk->sk_family);
|
|
+
|
|
+ if (family == AF_INET)
|
|
return ip_recv_error(sk, msg, len, addr_len);
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
- if (sk->sk_family == AF_INET6)
|
|
+ if (family == AF_INET6)
|
|
return pingv6_ops.ipv6_recv_error(sk, msg, len, addr_len);
|
|
#endif
|
|
return -EINVAL;
|
|
diff --git net/ipv4/ip_output.c net/ipv4/ip_output.c
|
|
index c242c412dabc..947655e4ab5c 100644
|
|
--- net/ipv4/ip_output.c
|
|
+++ net/ipv4/ip_output.c
|
|
@@ -1114,6 +1114,16 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
|
|
struct ip_options_rcu *opt;
|
|
struct rtable *rt;
|
|
|
|
+ rt = *rtp;
|
|
+ if (unlikely(!rt))
|
|
+ return -EFAULT;
|
|
+
|
|
+ cork->fragsize = ip_sk_use_pmtu(sk) ?
|
|
+ dst_mtu(&rt->dst) : READ_ONCE(rt->dst.dev->mtu);
|
|
+
|
|
+ if (!inetdev_valid_mtu(cork->fragsize))
|
|
+ return -ENETUNREACH;
|
|
+
|
|
/*
|
|
* setup for corking.
|
|
*/
|
|
@@ -1129,15 +1139,6 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
|
|
cork->flags |= IPCORK_OPT;
|
|
cork->addr = ipc->addr;
|
|
}
|
|
- rt = *rtp;
|
|
- if (unlikely(!rt))
|
|
- return -EFAULT;
|
|
-
|
|
- cork->fragsize = ip_sk_use_pmtu(sk) ?
|
|
- dst_mtu(&rt->dst) : READ_ONCE(rt->dst.dev->mtu);
|
|
-
|
|
- if (!inetdev_valid_mtu(cork->fragsize))
|
|
- return -ENETUNREACH;
|
|
|
|
cork->dst = &rt->dst;
|
|
/* We stole this route, caller should not release it. */
|
|
diff --git net/ipv4/tcp.c net/ipv4/tcp.c
|
|
index 0859f968c9b2..eb5458cbdc1c 100644
|
|
--- net/ipv4/tcp.c
|
|
+++ net/ipv4/tcp.c
|
|
@@ -701,6 +701,7 @@ static void tcp_push(struct sock *sk, int flags, int mss_now,
|
|
if (!test_bit(TSQ_THROTTLED, &sk->sk_tsq_flags)) {
|
|
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTOCORKING);
|
|
set_bit(TSQ_THROTTLED, &sk->sk_tsq_flags);
|
|
+ smp_mb__after_atomic();
|
|
}
|
|
/* It is possible TX completion already happened
|
|
* before we set TSQ_THROTTLED.
|
|
diff --git net/ipv6/addrconf_core.c net/ipv6/addrconf_core.c
|
|
index e6c5a4b5921d..f5a267972c57 100644
|
|
--- net/ipv6/addrconf_core.c
|
|
+++ net/ipv6/addrconf_core.c
|
|
@@ -140,19 +140,26 @@ const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
|
|
EXPORT_SYMBOL_GPL(ipv6_stub);
|
|
|
|
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
|
|
-const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
|
|
+const struct in6_addr in6addr_loopback __aligned(BITS_PER_LONG/8)
|
|
+ = IN6ADDR_LOOPBACK_INIT;
|
|
EXPORT_SYMBOL(in6addr_loopback);
|
|
-const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
|
+const struct in6_addr in6addr_any __aligned(BITS_PER_LONG/8)
|
|
+ = IN6ADDR_ANY_INIT;
|
|
EXPORT_SYMBOL(in6addr_any);
|
|
-const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
|
|
+const struct in6_addr in6addr_linklocal_allnodes __aligned(BITS_PER_LONG/8)
|
|
+ = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
|
|
EXPORT_SYMBOL(in6addr_linklocal_allnodes);
|
|
-const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
|
|
+const struct in6_addr in6addr_linklocal_allrouters __aligned(BITS_PER_LONG/8)
|
|
+ = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
|
|
EXPORT_SYMBOL(in6addr_linklocal_allrouters);
|
|
-const struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
|
|
+const struct in6_addr in6addr_interfacelocal_allnodes __aligned(BITS_PER_LONG/8)
|
|
+ = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
|
|
EXPORT_SYMBOL(in6addr_interfacelocal_allnodes);
|
|
-const struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
|
|
+const struct in6_addr in6addr_interfacelocal_allrouters __aligned(BITS_PER_LONG/8)
|
|
+ = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
|
|
EXPORT_SYMBOL(in6addr_interfacelocal_allrouters);
|
|
-const struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
|
|
+const struct in6_addr in6addr_sitelocal_allrouters __aligned(BITS_PER_LONG/8)
|
|
+ = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
|
|
EXPORT_SYMBOL(in6addr_sitelocal_allrouters);
|
|
|
|
static void snmp6_free_dev(struct inet6_dev *idev)
|
|
diff --git net/ipv6/ip6_tunnel.c net/ipv6/ip6_tunnel.c
|
|
index d59bf0da2912..cfe3a72a1159 100644
|
|
--- net/ipv6/ip6_tunnel.c
|
|
+++ net/ipv6/ip6_tunnel.c
|
|
@@ -404,7 +404,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
|
|
const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
|
|
unsigned int nhoff = raw - skb->data;
|
|
unsigned int off = nhoff + sizeof(*ipv6h);
|
|
- u8 next, nexthdr = ipv6h->nexthdr;
|
|
+ u8 nexthdr = ipv6h->nexthdr;
|
|
|
|
while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
|
|
struct ipv6_opt_hdr *hdr;
|
|
@@ -415,25 +415,25 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
|
|
|
|
hdr = (struct ipv6_opt_hdr *)(skb->data + off);
|
|
if (nexthdr == NEXTHDR_FRAGMENT) {
|
|
- struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
|
|
- if (frag_hdr->frag_off)
|
|
- break;
|
|
optlen = 8;
|
|
} else if (nexthdr == NEXTHDR_AUTH) {
|
|
optlen = (hdr->hdrlen + 2) << 2;
|
|
} else {
|
|
optlen = ipv6_optlen(hdr);
|
|
}
|
|
- /* cache hdr->nexthdr, since pskb_may_pull() might
|
|
- * invalidate hdr
|
|
- */
|
|
- next = hdr->nexthdr;
|
|
- if (nexthdr == NEXTHDR_DEST) {
|
|
- u16 i = 2;
|
|
|
|
- /* Remember : hdr is no longer valid at this point. */
|
|
- if (!pskb_may_pull(skb, off + optlen))
|
|
+ if (!pskb_may_pull(skb, off + optlen))
|
|
+ break;
|
|
+
|
|
+ hdr = (struct ipv6_opt_hdr *)(skb->data + off);
|
|
+ if (nexthdr == NEXTHDR_FRAGMENT) {
|
|
+ struct frag_hdr *frag_hdr = (struct frag_hdr *)hdr;
|
|
+
|
|
+ if (frag_hdr->frag_off)
|
|
break;
|
|
+ }
|
|
+ if (nexthdr == NEXTHDR_DEST) {
|
|
+ u16 i = 2;
|
|
|
|
while (1) {
|
|
struct ipv6_tlv_tnl_enc_lim *tel;
|
|
@@ -454,7 +454,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
|
|
i++;
|
|
}
|
|
}
|
|
- nexthdr = next;
|
|
+ nexthdr = hdr->nexthdr;
|
|
off += optlen;
|
|
}
|
|
return 0;
|
|
diff --git net/ipv6/route.c net/ipv6/route.c
|
|
index 79b67f8048b5..6e4d31524268 100644
|
|
--- net/ipv6/route.c
|
|
+++ net/ipv6/route.c
|
|
@@ -85,7 +85,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *);
|
|
static void ip6_dst_destroy(struct dst_entry *);
|
|
static void ip6_dst_ifdown(struct dst_entry *,
|
|
struct net_device *dev, int how);
|
|
-static int ip6_dst_gc(struct dst_ops *ops);
|
|
+static void ip6_dst_gc(struct dst_ops *ops);
|
|
|
|
static int ip6_pkt_discard(struct sk_buff *skb);
|
|
static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb);
|
|
@@ -1792,29 +1792,30 @@ out:
|
|
return dst;
|
|
}
|
|
|
|
-static int ip6_dst_gc(struct dst_ops *ops)
|
|
+static void ip6_dst_gc(struct dst_ops *ops)
|
|
{
|
|
struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
|
|
int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
|
|
- int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
|
|
int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
|
|
int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
|
|
unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
|
|
+ unsigned int val;
|
|
int entries;
|
|
|
|
entries = dst_entries_get_fast(ops);
|
|
- if (time_after(rt_last_gc + rt_min_interval, jiffies) &&
|
|
- entries <= rt_max_size)
|
|
+ if (entries > ops->gc_thresh)
|
|
+ entries = dst_entries_get_slow(ops);
|
|
+
|
|
+ if (time_after(rt_last_gc + rt_min_interval, jiffies))
|
|
goto out;
|
|
|
|
- net->ipv6.ip6_rt_gc_expire++;
|
|
- fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, true);
|
|
+ fib6_run_gc(atomic_inc_return(&net->ipv6.ip6_rt_gc_expire), net, true);
|
|
entries = dst_entries_get_slow(ops);
|
|
if (entries < ops->gc_thresh)
|
|
- net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
|
|
+ atomic_set(&net->ipv6.ip6_rt_gc_expire, rt_gc_timeout >> 1);
|
|
out:
|
|
- net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
|
|
- return entries > rt_max_size;
|
|
+ val = atomic_read(&net->ipv6.ip6_rt_gc_expire);
|
|
+ atomic_set(&net->ipv6.ip6_rt_gc_expire, val - (val >> rt_elasticity));
|
|
}
|
|
|
|
static int ip6_convert_metrics(struct mx6_config *mxc,
|
|
@@ -4091,7 +4092,7 @@ static int __net_init ip6_route_net_init(struct net *net)
|
|
#endif
|
|
|
|
net->ipv6.sysctl.flush_delay = 0;
|
|
- net->ipv6.sysctl.ip6_rt_max_size = 4096;
|
|
+ net->ipv6.sysctl.ip6_rt_max_size = INT_MAX;
|
|
net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2;
|
|
net->ipv6.sysctl.ip6_rt_gc_timeout = 60*HZ;
|
|
net->ipv6.sysctl.ip6_rt_gc_interval = 30*HZ;
|
|
@@ -4099,7 +4100,7 @@ static int __net_init ip6_route_net_init(struct net *net)
|
|
net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ;
|
|
net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
|
|
|
|
- net->ipv6.ip6_rt_gc_expire = 30*HZ;
|
|
+ atomic_set(&net->ipv6.ip6_rt_gc_expire, 30*HZ);
|
|
|
|
ret = 0;
|
|
out:
|
|
diff --git net/ipv6/seg6.c net/ipv6/seg6.c
|
|
index 9c45165fe79b..b785bf569049 100644
|
|
--- net/ipv6/seg6.c
|
|
+++ net/ipv6/seg6.c
|
|
@@ -447,22 +447,24 @@ int __init seg6_init(void)
|
|
{
|
|
int err = -ENOMEM;
|
|
|
|
- err = genl_register_family(&seg6_genl_family);
|
|
+ err = register_pernet_subsys(&ip6_segments_ops);
|
|
if (err)
|
|
goto out;
|
|
|
|
- err = register_pernet_subsys(&ip6_segments_ops);
|
|
+ err = genl_register_family(&seg6_genl_family);
|
|
if (err)
|
|
- goto out_unregister_genl;
|
|
+ goto out_unregister_pernet;
|
|
|
|
#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
|
|
err = seg6_iptunnel_init();
|
|
if (err)
|
|
- goto out_unregister_pernet;
|
|
+ goto out_unregister_genl;
|
|
|
|
err = seg6_local_init();
|
|
- if (err)
|
|
- goto out_unregister_pernet;
|
|
+ if (err) {
|
|
+ seg6_iptunnel_exit();
|
|
+ goto out_unregister_genl;
|
|
+ }
|
|
#endif
|
|
|
|
#ifdef CONFIG_IPV6_SEG6_HMAC
|
|
@@ -483,11 +485,11 @@ out_unregister_iptun:
|
|
#endif
|
|
#endif
|
|
#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
|
|
-out_unregister_pernet:
|
|
- unregister_pernet_subsys(&ip6_segments_ops);
|
|
-#endif
|
|
out_unregister_genl:
|
|
genl_unregister_family(&seg6_genl_family);
|
|
+#endif
|
|
+out_unregister_pernet:
|
|
+ unregister_pernet_subsys(&ip6_segments_ops);
|
|
goto out;
|
|
}
|
|
|
|
diff --git net/iucv/af_iucv.c net/iucv/af_iucv.c
|
|
index 07e397a5edc6..d7dd92274957 100644
|
|
--- net/iucv/af_iucv.c
|
|
+++ net/iucv/af_iucv.c
|
|
@@ -2458,7 +2458,7 @@ static int __init afiucv_init(void)
|
|
{
|
|
int err;
|
|
|
|
- if (MACHINE_IS_VM) {
|
|
+ if (MACHINE_IS_VM && IS_ENABLED(CONFIG_IUCV)) {
|
|
cpcmd("QUERY USERID", iucv_userid, sizeof(iucv_userid), &err);
|
|
if (unlikely(err)) {
|
|
WARN_ON(err);
|
|
@@ -2466,11 +2466,7 @@ static int __init afiucv_init(void)
|
|
goto out;
|
|
}
|
|
|
|
- pr_iucv = try_then_request_module(symbol_get(iucv_if), "iucv");
|
|
- if (!pr_iucv) {
|
|
- printk(KERN_WARNING "iucv_if lookup failed\n");
|
|
- memset(&iucv_userid, 0, sizeof(iucv_userid));
|
|
- }
|
|
+ pr_iucv = &iucv_if;
|
|
} else {
|
|
memset(&iucv_userid, 0, sizeof(iucv_userid));
|
|
pr_iucv = NULL;
|
|
@@ -2504,17 +2500,13 @@ out_sock:
|
|
out_proto:
|
|
proto_unregister(&iucv_proto);
|
|
out:
|
|
- if (pr_iucv)
|
|
- symbol_put(iucv_if);
|
|
return err;
|
|
}
|
|
|
|
static void __exit afiucv_exit(void)
|
|
{
|
|
- if (pr_iucv) {
|
|
+ if (pr_iucv)
|
|
afiucv_iucv_exit();
|
|
- symbol_put(iucv_if);
|
|
- }
|
|
|
|
unregister_netdevice_notifier(&afiucv_netdev_notifier);
|
|
dev_remove_pack(&iucv_packet_type);
|
|
diff --git net/l2tp/l2tp_ip6.c net/l2tp/l2tp_ip6.c
|
|
index d797708a1a5e..4a5f6ca12342 100644
|
|
--- net/l2tp/l2tp_ip6.c
|
|
+++ net/l2tp/l2tp_ip6.c
|
|
@@ -658,7 +658,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|
|
|
back_from_confirm:
|
|
lock_sock(sk);
|
|
- ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0;
|
|
+ ulen = len + (skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0);
|
|
err = ip6_append_data(sk, ip_generic_getfrag, msg,
|
|
ulen, transhdrlen, &ipc6,
|
|
&fl6, (struct rt6_info *)dst,
|
|
diff --git net/llc/af_llc.c net/llc/af_llc.c
|
|
index 1e20b719fb3c..727af511297c 100644
|
|
--- net/llc/af_llc.c
|
|
+++ net/llc/af_llc.c
|
|
@@ -227,6 +227,8 @@ static int llc_ui_release(struct socket *sock)
|
|
if (llc->dev)
|
|
dev_put(llc->dev);
|
|
sock_put(sk);
|
|
+ sock_orphan(sk);
|
|
+ sock->sk = NULL;
|
|
llc_sk_free(sk);
|
|
out:
|
|
return 0;
|
|
@@ -926,14 +928,15 @@ copy_uaddr:
|
|
*/
|
|
static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
|
|
{
|
|
+ DECLARE_SOCKADDR(struct sockaddr_llc *, addr, msg->msg_name);
|
|
struct sock *sk = sock->sk;
|
|
struct llc_sock *llc = llc_sk(sk);
|
|
- DECLARE_SOCKADDR(struct sockaddr_llc *, addr, msg->msg_name);
|
|
int flags = msg->msg_flags;
|
|
int noblock = flags & MSG_DONTWAIT;
|
|
+ int rc = -EINVAL, copied = 0, hdrlen, hh_len;
|
|
struct sk_buff *skb = NULL;
|
|
+ struct net_device *dev;
|
|
size_t size = 0;
|
|
- int rc = -EINVAL, copied = 0, hdrlen;
|
|
|
|
dprintk("%s: sending from %02X to %02X\n", __func__,
|
|
llc->laddr.lsap, llc->daddr.lsap);
|
|
@@ -953,22 +956,29 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
|
|
if (rc)
|
|
goto out;
|
|
}
|
|
- hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr);
|
|
+ dev = llc->dev;
|
|
+ hh_len = LL_RESERVED_SPACE(dev);
|
|
+ hdrlen = llc_ui_header_len(sk, addr);
|
|
size = hdrlen + len;
|
|
- if (size > llc->dev->mtu)
|
|
- size = llc->dev->mtu;
|
|
+ size = min_t(size_t, size, READ_ONCE(dev->mtu));
|
|
copied = size - hdrlen;
|
|
rc = -EINVAL;
|
|
if (copied < 0)
|
|
goto out;
|
|
release_sock(sk);
|
|
- skb = sock_alloc_send_skb(sk, size, noblock, &rc);
|
|
+ skb = sock_alloc_send_skb(sk, hh_len + size, noblock, &rc);
|
|
lock_sock(sk);
|
|
if (!skb)
|
|
goto out;
|
|
- skb->dev = llc->dev;
|
|
+ if (sock_flag(sk, SOCK_ZAPPED) ||
|
|
+ llc->dev != dev ||
|
|
+ hdrlen != llc_ui_header_len(sk, addr) ||
|
|
+ hh_len != LL_RESERVED_SPACE(dev) ||
|
|
+ size > READ_ONCE(dev->mtu))
|
|
+ goto out;
|
|
+ skb->dev = dev;
|
|
skb->protocol = llc_proto_type(addr->sllc_arphrd);
|
|
- skb_reserve(skb, hdrlen);
|
|
+ skb_reserve(skb, hh_len + hdrlen);
|
|
rc = memcpy_from_msg(skb_put(skb, copied), msg, copied);
|
|
if (rc)
|
|
goto out;
|
|
diff --git net/llc/llc_core.c net/llc/llc_core.c
|
|
index 64d4bef04e73..4900a27b5176 100644
|
|
--- net/llc/llc_core.c
|
|
+++ net/llc/llc_core.c
|
|
@@ -135,22 +135,15 @@ static struct packet_type llc_packet_type __read_mostly = {
|
|
.func = llc_rcv,
|
|
};
|
|
|
|
-static struct packet_type llc_tr_packet_type __read_mostly = {
|
|
- .type = cpu_to_be16(ETH_P_TR_802_2),
|
|
- .func = llc_rcv,
|
|
-};
|
|
-
|
|
static int __init llc_init(void)
|
|
{
|
|
dev_add_pack(&llc_packet_type);
|
|
- dev_add_pack(&llc_tr_packet_type);
|
|
return 0;
|
|
}
|
|
|
|
static void __exit llc_exit(void)
|
|
{
|
|
dev_remove_pack(&llc_packet_type);
|
|
- dev_remove_pack(&llc_tr_packet_type);
|
|
}
|
|
|
|
module_init(llc_init);
|
|
diff --git net/mac80211/sta_info.c net/mac80211/sta_info.c
|
|
index 4e406cd11573..f2663c0a1e6f 100644
|
|
--- net/mac80211/sta_info.c
|
|
+++ net/mac80211/sta_info.c
|
|
@@ -602,6 +602,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
|
if (ieee80211_vif_is_mesh(&sdata->vif))
|
|
mesh_accept_plinks_update(sdata);
|
|
|
|
+ ieee80211_check_fast_xmit(sta);
|
|
+
|
|
return 0;
|
|
out_remove:
|
|
sta_info_hash_del(local, sta);
|
|
diff --git net/mac80211/tx.c net/mac80211/tx.c
|
|
index 3914214dee05..995b0f444351 100644
|
|
--- net/mac80211/tx.c
|
|
+++ net/mac80211/tx.c
|
|
@@ -2808,7 +2808,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
|
|
sdata->vif.type == NL80211_IFTYPE_STATION)
|
|
goto out;
|
|
|
|
- if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
|
+ if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED) || !sta->uploaded)
|
|
goto out;
|
|
|
|
if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
|
|
diff --git net/ncsi/internal.h net/ncsi/internal.h
|
|
index 8055e3965cef..2477caf9c967 100644
|
|
--- net/ncsi/internal.h
|
|
+++ net/ncsi/internal.h
|
|
@@ -69,9 +69,12 @@ enum {
|
|
};
|
|
|
|
struct ncsi_channel_version {
|
|
- u32 version; /* Supported BCD encoded NCSI version */
|
|
- u32 alpha2; /* Supported BCD encoded NCSI version */
|
|
- u8 fw_name[12]; /* Firware name string */
|
|
+ u8 major; /* NCSI version major */
|
|
+ u8 minor; /* NCSI version minor */
|
|
+ u8 update; /* NCSI version update */
|
|
+ char alpha1; /* NCSI version alpha1 */
|
|
+ char alpha2; /* NCSI version alpha2 */
|
|
+ u8 fw_name[12]; /* Firmware name string */
|
|
u32 fw_version; /* Firmware version */
|
|
u16 pci_ids[4]; /* PCI identification */
|
|
u32 mf_id; /* Manufacture ID */
|
|
diff --git net/ncsi/ncsi-netlink.c net/ncsi/ncsi-netlink.c
|
|
index 9073911ac97b..5c88201ec9d8 100644
|
|
--- net/ncsi/ncsi-netlink.c
|
|
+++ net/ncsi/ncsi-netlink.c
|
|
@@ -71,8 +71,8 @@ static int ncsi_write_channel_info(struct sk_buff *skb,
|
|
if (ndp->force_channel == nc)
|
|
nla_put_flag(skb, NCSI_CHANNEL_ATTR_FORCED);
|
|
|
|
- nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MAJOR, nc->version.version);
|
|
- nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MINOR, nc->version.alpha2);
|
|
+ nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MAJOR, nc->version.major);
|
|
+ nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MINOR, nc->version.minor);
|
|
nla_put_string(skb, NCSI_CHANNEL_ATTR_VERSION_STR, nc->version.fw_name);
|
|
|
|
vid_nest = nla_nest_start(skb, NCSI_CHANNEL_ATTR_VLAN_LIST);
|
|
diff --git net/ncsi/ncsi-pkt.h net/ncsi/ncsi-pkt.h
|
|
index 91b4b66438df..0bf62b4883d4 100644
|
|
--- net/ncsi/ncsi-pkt.h
|
|
+++ net/ncsi/ncsi-pkt.h
|
|
@@ -164,9 +164,12 @@ struct ncsi_rsp_gls_pkt {
|
|
/* Get Version ID */
|
|
struct ncsi_rsp_gvi_pkt {
|
|
struct ncsi_rsp_pkt_hdr rsp; /* Response header */
|
|
- __be32 ncsi_version; /* NCSI version */
|
|
+ unsigned char major; /* NCSI version major */
|
|
+ unsigned char minor; /* NCSI version minor */
|
|
+ unsigned char update; /* NCSI version update */
|
|
+ unsigned char alpha1; /* NCSI version alpha1 */
|
|
unsigned char reserved[3]; /* Reserved */
|
|
- unsigned char alpha2; /* NCSI version */
|
|
+ unsigned char alpha2; /* NCSI version alpha2 */
|
|
unsigned char fw_name[12]; /* f/w name string */
|
|
__be32 fw_version; /* f/w version */
|
|
__be16 pci_ids[4]; /* PCI IDs */
|
|
diff --git net/ncsi/ncsi-rsp.c net/ncsi/ncsi-rsp.c
|
|
index 42878d843c3c..1ae1de24b202 100644
|
|
--- net/ncsi/ncsi-rsp.c
|
|
+++ net/ncsi/ncsi-rsp.c
|
|
@@ -20,6 +20,19 @@
|
|
#include "internal.h"
|
|
#include "ncsi-pkt.h"
|
|
|
|
+/* Nibbles within [0xA, 0xF] add zero "0" to the returned value.
|
|
+ * Optional fields (encoded as 0xFF) will default to zero.
|
|
+ */
|
|
+static u8 decode_bcd_u8(u8 x)
|
|
+{
|
|
+ int lo = x & 0xF;
|
|
+ int hi = x >> 4;
|
|
+
|
|
+ lo = lo < 0xA ? lo : 0;
|
|
+ hi = hi < 0xA ? hi : 0;
|
|
+ return lo + hi * 10;
|
|
+}
|
|
+
|
|
static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
|
|
unsigned short payload)
|
|
{
|
|
@@ -610,9 +623,18 @@ static int ncsi_rsp_handler_gvi(struct ncsi_request *nr)
|
|
if (!nc)
|
|
return -ENODEV;
|
|
|
|
- /* Update to channel's version info */
|
|
+ /* Update channel's version info
|
|
+ *
|
|
+ * Major, minor, and update fields are supposed to be
|
|
+ * unsigned integers encoded as packed BCD.
|
|
+ *
|
|
+ * Alpha1 and alpha2 are ISO/IEC 8859-1 characters.
|
|
+ */
|
|
ncv = &nc->version;
|
|
- ncv->version = ntohl(rsp->ncsi_version);
|
|
+ ncv->major = decode_bcd_u8(rsp->major);
|
|
+ ncv->minor = decode_bcd_u8(rsp->minor);
|
|
+ ncv->update = decode_bcd_u8(rsp->update);
|
|
+ ncv->alpha1 = rsp->alpha1;
|
|
ncv->alpha2 = rsp->alpha2;
|
|
memcpy(ncv->fw_name, rsp->fw_name, 12);
|
|
ncv->fw_version = ntohl(rsp->fw_version);
|
|
diff --git net/netfilter/ipvs/ip_vs_xmit.c net/netfilter/ipvs/ip_vs_xmit.c
|
|
index 97d411033f8a..8792cad28e29 100644
|
|
--- net/netfilter/ipvs/ip_vs_xmit.c
|
|
+++ net/netfilter/ipvs/ip_vs_xmit.c
|
|
@@ -270,8 +270,8 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs,
|
|
skb->dev = dst->dev;
|
|
icmpv6_send(skb, ICMPV6_TIME_EXCEED,
|
|
ICMPV6_EXC_HOPLIMIT, 0);
|
|
- __IP6_INC_STATS(net, ip6_dst_idev(dst),
|
|
- IPSTATS_MIB_INHDRERRORS);
|
|
+ IP6_INC_STATS(net, ip6_dst_idev(dst),
|
|
+ IPSTATS_MIB_INHDRERRORS);
|
|
|
|
return false;
|
|
}
|
|
@@ -286,7 +286,7 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs,
|
|
{
|
|
if (ip_hdr(skb)->ttl <= 1) {
|
|
/* Tell the sender its packet died... */
|
|
- __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
|
|
+ IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
|
|
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
|
|
return false;
|
|
}
|
|
diff --git net/netfilter/nf_log.c net/netfilter/nf_log.c
|
|
index cdc744aa5889..a16156598905 100644
|
|
--- net/netfilter/nf_log.c
|
|
+++ net/netfilter/nf_log.c
|
|
@@ -202,11 +202,12 @@ void nf_logger_put(int pf, enum nf_log_type type)
|
|
return;
|
|
}
|
|
|
|
- BUG_ON(loggers[pf][type] == NULL);
|
|
-
|
|
rcu_read_lock();
|
|
logger = rcu_dereference(loggers[pf][type]);
|
|
- module_put(logger->me);
|
|
+ if (!logger)
|
|
+ WARN_ON_ONCE(1);
|
|
+ else
|
|
+ module_put(logger->me);
|
|
rcu_read_unlock();
|
|
}
|
|
EXPORT_SYMBOL_GPL(nf_logger_put);
|
|
diff --git net/netfilter/nf_tables_api.c net/netfilter/nf_tables_api.c
|
|
index 27c24c99d23b..407346ba89d4 100644
|
|
--- net/netfilter/nf_tables_api.c
|
|
+++ net/netfilter/nf_tables_api.c
|
|
@@ -22,6 +22,8 @@
|
|
#include <net/net_namespace.h>
|
|
#include <net/sock.h>
|
|
|
|
+#define NFT_SET_MAX_ANONLEN 16
|
|
+
|
|
static LIST_HEAD(nf_tables_expressions);
|
|
static LIST_HEAD(nf_tables_objects);
|
|
|
|
@@ -744,6 +746,30 @@ err:
|
|
return ret;
|
|
}
|
|
|
|
+static bool nft_supported_family(u8 family)
|
|
+{
|
|
+ return false
|
|
+#ifdef CONFIG_NF_TABLES_INET
|
|
+ || family == NFPROTO_INET
|
|
+#endif
|
|
+#ifdef CONFIG_NF_TABLES_IPV4
|
|
+ || family == NFPROTO_IPV4
|
|
+#endif
|
|
+#ifdef CONFIG_NF_TABLES_ARP
|
|
+ || family == NFPROTO_ARP
|
|
+#endif
|
|
+#ifdef CONFIG_NF_TABLES_NETDEV
|
|
+ || family == NFPROTO_NETDEV
|
|
+#endif
|
|
+#if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE)
|
|
+ || family == NFPROTO_BRIDGE
|
|
+#endif
|
|
+#ifdef CONFIG_NF_TABLES_IPV6
|
|
+ || family == NFPROTO_IPV6
|
|
+#endif
|
|
+ ;
|
|
+}
|
|
+
|
|
static int nf_tables_newtable(struct net *net, struct sock *nlsk,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
const struct nlattr * const nla[],
|
|
@@ -759,6 +785,9 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
|
|
struct nft_ctx ctx;
|
|
int err;
|
|
|
|
+ if (!nft_supported_family(family))
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
afi = nf_tables_afinfo_lookup(net, family, true);
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
@@ -2817,6 +2846,9 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
|
|
if (p[1] != 'd' || strchr(p + 2, '%'))
|
|
return -EINVAL;
|
|
|
|
+ if (strnlen(name, NFT_SET_MAX_ANONLEN) >= NFT_SET_MAX_ANONLEN)
|
|
+ return -EINVAL;
|
|
+
|
|
inuse = (unsigned long *)get_zeroed_page(GFP_KERNEL);
|
|
if (inuse == NULL)
|
|
return -ENOMEM;
|
|
@@ -5889,16 +5921,10 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
|
|
data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE]));
|
|
|
|
switch (data->verdict.code) {
|
|
- default:
|
|
- switch (data->verdict.code & NF_VERDICT_MASK) {
|
|
- case NF_ACCEPT:
|
|
- case NF_DROP:
|
|
- case NF_QUEUE:
|
|
- break;
|
|
- default:
|
|
- return -EINVAL;
|
|
- }
|
|
- /* fall through */
|
|
+ case NF_ACCEPT:
|
|
+ case NF_DROP:
|
|
+ case NF_QUEUE:
|
|
+ break;
|
|
case NFT_CONTINUE:
|
|
case NFT_BREAK:
|
|
case NFT_RETURN:
|
|
@@ -5918,6 +5944,8 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
|
|
|
|
data->verdict.chain = chain;
|
|
break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
desc->len = sizeof(data->verdict);
|
|
diff --git net/netfilter/nft_byteorder.c net/netfilter/nft_byteorder.c
|
|
index dba16126c7ee..8c4ee49a80fb 100644
|
|
--- net/netfilter/nft_byteorder.c
|
|
+++ net/netfilter/nft_byteorder.c
|
|
@@ -41,19 +41,20 @@ static void nft_byteorder_eval(const struct nft_expr *expr,
|
|
|
|
switch (priv->size) {
|
|
case 8: {
|
|
+ u64 *dst64 = (void *)dst;
|
|
u64 src64;
|
|
|
|
switch (priv->op) {
|
|
case NFT_BYTEORDER_NTOH:
|
|
for (i = 0; i < priv->len / 8; i++) {
|
|
src64 = get_unaligned((u64 *)&src[i]);
|
|
- put_unaligned_be64(src64, &dst[i]);
|
|
+ put_unaligned_be64(src64, &dst64[i]);
|
|
}
|
|
break;
|
|
case NFT_BYTEORDER_HTON:
|
|
for (i = 0; i < priv->len / 8; i++) {
|
|
src64 = get_unaligned_be64(&src[i]);
|
|
- put_unaligned(src64, (u64 *)&dst[i]);
|
|
+ put_unaligned(src64, &dst64[i]);
|
|
}
|
|
break;
|
|
}
|
|
diff --git net/netfilter/nft_compat.c net/netfilter/nft_compat.c
|
|
index 8281656808ae..b87b7338266c 100644
|
|
--- net/netfilter/nft_compat.c
|
|
+++ net/netfilter/nft_compat.c
|
|
@@ -214,6 +214,7 @@ static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1]
|
|
static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
|
|
{
|
|
struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1];
|
|
+ u32 l4proto;
|
|
u32 flags;
|
|
int err;
|
|
|
|
@@ -226,12 +227,18 @@ static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
|
|
return -EINVAL;
|
|
|
|
flags = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_FLAGS]));
|
|
- if (flags & ~NFT_RULE_COMPAT_F_MASK)
|
|
+ if (flags & NFT_RULE_COMPAT_F_UNUSED ||
|
|
+ flags & ~NFT_RULE_COMPAT_F_MASK)
|
|
return -EINVAL;
|
|
if (flags & NFT_RULE_COMPAT_F_INV)
|
|
*inv = true;
|
|
|
|
- *proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
|
|
+ l4proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
|
|
+ if (l4proto > U16_MAX)
|
|
+ return -EINVAL;
|
|
+
|
|
+ *proto = l4proto;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git net/netlabel/netlabel_calipso.c net/netlabel/netlabel_calipso.c
|
|
index d177dd066504..e0d63fb927bd 100644
|
|
--- net/netlabel/netlabel_calipso.c
|
|
+++ net/netlabel/netlabel_calipso.c
|
|
@@ -68,6 +68,28 @@ static const struct nla_policy calipso_genl_policy[NLBL_CALIPSO_A_MAX + 1] = {
|
|
[NLBL_CALIPSO_A_MTYPE] = { .type = NLA_U32 },
|
|
};
|
|
|
|
+static const struct netlbl_calipso_ops *calipso_ops;
|
|
+
|
|
+/**
|
|
+ * netlbl_calipso_ops_register - Register the CALIPSO operations
|
|
+ * @ops: ops to register
|
|
+ *
|
|
+ * Description:
|
|
+ * Register the CALIPSO packet engine operations.
|
|
+ *
|
|
+ */
|
|
+const struct netlbl_calipso_ops *
|
|
+netlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops)
|
|
+{
|
|
+ return xchg(&calipso_ops, ops);
|
|
+}
|
|
+EXPORT_SYMBOL(netlbl_calipso_ops_register);
|
|
+
|
|
+static const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void)
|
|
+{
|
|
+ return ACCESS_ONCE(calipso_ops);
|
|
+}
|
|
+
|
|
/* NetLabel Command Handlers
|
|
*/
|
|
/**
|
|
@@ -110,16 +132,19 @@ static int netlbl_calipso_add_pass(struct genl_info *info,
|
|
*
|
|
*/
|
|
static int netlbl_calipso_add(struct sk_buff *skb, struct genl_info *info)
|
|
-
|
|
{
|
|
int ret_val = -EINVAL;
|
|
struct netlbl_audit audit_info;
|
|
+ const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
|
|
|
|
if (!info->attrs[NLBL_CALIPSO_A_DOI] ||
|
|
!info->attrs[NLBL_CALIPSO_A_MTYPE])
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ if (!ops)
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
switch (nla_get_u32(info->attrs[NLBL_CALIPSO_A_MTYPE])) {
|
|
case CALIPSO_MAP_PASS:
|
|
ret_val = netlbl_calipso_add_pass(info, &audit_info);
|
|
@@ -301,7 +326,7 @@ static int netlbl_calipso_remove(struct sk_buff *skb, struct genl_info *info)
|
|
if (!info->attrs[NLBL_CALIPSO_A_DOI])
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
cb_arg.doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
|
|
cb_arg.audit_info = &audit_info;
|
|
ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
|
|
@@ -375,27 +400,6 @@ int __init netlbl_calipso_genl_init(void)
|
|
return genl_register_family(&netlbl_calipso_gnl_family);
|
|
}
|
|
|
|
-static const struct netlbl_calipso_ops *calipso_ops;
|
|
-
|
|
-/**
|
|
- * netlbl_calipso_ops_register - Register the CALIPSO operations
|
|
- *
|
|
- * Description:
|
|
- * Register the CALIPSO packet engine operations.
|
|
- *
|
|
- */
|
|
-const struct netlbl_calipso_ops *
|
|
-netlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops)
|
|
-{
|
|
- return xchg(&calipso_ops, ops);
|
|
-}
|
|
-EXPORT_SYMBOL(netlbl_calipso_ops_register);
|
|
-
|
|
-static const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void)
|
|
-{
|
|
- return ACCESS_ONCE(calipso_ops);
|
|
-}
|
|
-
|
|
/**
|
|
* calipso_doi_add - Add a new DOI to the CALIPSO protocol engine
|
|
* @doi_def: the DOI structure
|
|
diff --git net/netlabel/netlabel_cipso_v4.c net/netlabel/netlabel_cipso_v4.c
|
|
index e252f62bb8c2..a0a145db3fc7 100644
|
|
--- net/netlabel/netlabel_cipso_v4.c
|
|
+++ net/netlabel/netlabel_cipso_v4.c
|
|
@@ -420,7 +420,7 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
|
|
!info->attrs[NLBL_CIPSOV4_A_MTYPE])
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) {
|
|
case CIPSO_V4_MAP_TRANS:
|
|
ret_val = netlbl_cipsov4_add_std(info, &audit_info);
|
|
@@ -715,7 +715,7 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
|
|
if (!info->attrs[NLBL_CIPSOV4_A_DOI])
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
cb_arg.doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
|
|
cb_arg.audit_info = &audit_info;
|
|
ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
|
|
diff --git net/netlabel/netlabel_mgmt.c net/netlabel/netlabel_mgmt.c
|
|
index 71ba69cb50c9..43c51242dcd2 100644
|
|
--- net/netlabel/netlabel_mgmt.c
|
|
+++ net/netlabel/netlabel_mgmt.c
|
|
@@ -447,7 +447,7 @@ static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
|
|
(info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
|
|
return netlbl_mgmt_add_common(info, &audit_info);
|
|
}
|
|
@@ -470,7 +470,7 @@ static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
|
|
if (!info->attrs[NLBL_MGMT_A_DOMAIN])
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
|
|
domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
|
|
return netlbl_domhsh_remove(domain, AF_UNSPEC, &audit_info);
|
|
@@ -570,7 +570,7 @@ static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
|
|
(info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
|
|
return netlbl_mgmt_add_common(info, &audit_info);
|
|
}
|
|
@@ -589,7 +589,7 @@ static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
|
|
{
|
|
struct netlbl_audit audit_info;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
|
|
return netlbl_domhsh_remove_default(AF_UNSPEC, &audit_info);
|
|
}
|
|
diff --git net/netlabel/netlabel_unlabeled.c net/netlabel/netlabel_unlabeled.c
|
|
index 0067f472367b..ff52ff2278ed 100644
|
|
--- net/netlabel/netlabel_unlabeled.c
|
|
+++ net/netlabel/netlabel_unlabeled.c
|
|
@@ -827,7 +827,7 @@ static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
|
|
if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
|
|
value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
|
|
if (value == 1 || value == 0) {
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
netlbl_unlabel_acceptflg_set(value, &audit_info);
|
|
return 0;
|
|
}
|
|
@@ -910,7 +910,7 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
|
|
!info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
|
|
ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
|
|
if (ret_val != 0)
|
|
@@ -960,7 +960,7 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
|
|
!info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
|
|
ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
|
|
if (ret_val != 0)
|
|
@@ -1007,7 +1007,7 @@ static int netlbl_unlabel_staticremove(struct sk_buff *skb,
|
|
!info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
|
|
ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
|
|
if (ret_val != 0)
|
|
@@ -1047,7 +1047,7 @@ static int netlbl_unlabel_staticremovedef(struct sk_buff *skb,
|
|
!info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
|
|
return -EINVAL;
|
|
|
|
- netlbl_netlink_auditinfo(skb, &audit_info);
|
|
+ netlbl_netlink_auditinfo(&audit_info);
|
|
|
|
ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
|
|
if (ret_val != 0)
|
|
diff --git net/netlabel/netlabel_user.h net/netlabel/netlabel_user.h
|
|
index 4a397cde1a48..2c608677b43b 100644
|
|
--- net/netlabel/netlabel_user.h
|
|
+++ net/netlabel/netlabel_user.h
|
|
@@ -42,11 +42,9 @@
|
|
|
|
/**
|
|
* netlbl_netlink_auditinfo - Fetch the audit information from a NETLINK msg
|
|
- * @skb: the packet
|
|
* @audit_info: NetLabel audit information
|
|
*/
|
|
-static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
|
|
- struct netlbl_audit *audit_info)
|
|
+static inline void netlbl_netlink_auditinfo(struct netlbl_audit *audit_info)
|
|
{
|
|
security_task_getsecid(current, &audit_info->secid);
|
|
audit_info->loginuid = audit_get_loginuid(current);
|
|
diff --git net/netlink/af_netlink.c net/netlink/af_netlink.c
|
|
index 89ece1f093e2..ee42244aada1 100644
|
|
--- net/netlink/af_netlink.c
|
|
+++ net/netlink/af_netlink.c
|
|
@@ -162,7 +162,7 @@ static inline u32 netlink_group_mask(u32 group)
|
|
static struct sk_buff *netlink_to_full_skb(const struct sk_buff *skb,
|
|
gfp_t gfp_mask)
|
|
{
|
|
- unsigned int len = skb_end_offset(skb);
|
|
+ unsigned int len = skb->len;
|
|
struct sk_buff *new;
|
|
|
|
new = alloc_skb(len, gfp_mask);
|
|
@@ -342,7 +342,7 @@ static void netlink_skb_destructor(struct sk_buff *skb)
|
|
if (is_vmalloc_addr(skb->head)) {
|
|
if (!skb->cloned ||
|
|
!atomic_dec_return(&(skb_shinfo(skb)->dataref)))
|
|
- vfree(skb->head);
|
|
+ vfree_atomic(skb->head);
|
|
|
|
skb->head = NULL;
|
|
}
|
|
diff --git net/nfc/nci/core.c net/nfc/nci/core.c
|
|
index d42c603dd635..2d9934dbbead 100644
|
|
--- net/nfc/nci/core.c
|
|
+++ net/nfc/nci/core.c
|
|
@@ -1209,6 +1209,10 @@ void nci_free_device(struct nci_dev *ndev)
|
|
{
|
|
nfc_free_device(ndev->nfc_dev);
|
|
nci_hci_deallocate(ndev);
|
|
+
|
|
+ /* drop partial rx data packet if present */
|
|
+ if (ndev->rx_data_reassembly)
|
|
+ kfree_skb(ndev->rx_data_reassembly);
|
|
kfree(ndev);
|
|
}
|
|
EXPORT_SYMBOL(nci_free_device);
|
|
diff --git net/packet/af_packet.c net/packet/af_packet.c
|
|
index ea29453fcf7a..6a02cf8d7141 100644
|
|
--- net/packet/af_packet.c
|
|
+++ net/packet/af_packet.c
|
|
@@ -1890,7 +1890,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
|
|
*/
|
|
|
|
spkt->spkt_family = dev->type;
|
|
- strlcpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
|
|
+ strscpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
|
|
spkt->spkt_protocol = skb->protocol;
|
|
|
|
/*
|
|
@@ -3537,7 +3537,7 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
|
|
rcu_read_lock();
|
|
dev = dev_get_by_index_rcu(sock_net(sk), READ_ONCE(pkt_sk(sk)->ifindex));
|
|
if (dev)
|
|
- strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
|
|
+ strscpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
|
|
rcu_read_unlock();
|
|
*uaddr_len = sizeof(*uaddr);
|
|
|
|
diff --git net/rds/af_rds.c net/rds/af_rds.c
|
|
index b405f77d664c..2628c1d3844e 100644
|
|
--- net/rds/af_rds.c
|
|
+++ net/rds/af_rds.c
|
|
@@ -315,7 +315,7 @@ static int rds_recv_track_latency(struct rds_sock *rs, char __user *optval,
|
|
|
|
rs->rs_rx_traces = trace.rx_traces;
|
|
for (i = 0; i < rs->rs_rx_traces; i++) {
|
|
- if (trace.rx_trace_pos[i] > RDS_MSG_RX_DGRAM_TRACE_MAX) {
|
|
+ if (trace.rx_trace_pos[i] >= RDS_MSG_RX_DGRAM_TRACE_MAX) {
|
|
rs->rs_rx_traces = 0;
|
|
return -EFAULT;
|
|
}
|
|
diff --git net/rxrpc/conn_event.c net/rxrpc/conn_event.c
|
|
index 2432c118397f..8d14aebae621 100644
|
|
--- net/rxrpc/conn_event.c
|
|
+++ net/rxrpc/conn_event.c
|
|
@@ -48,6 +48,14 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
|
|
|
|
_enter("%d", conn->debug_id);
|
|
|
|
+ if (sp && sp->hdr.type == RXRPC_PACKET_TYPE_ACK) {
|
|
+ if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
|
|
+ &pkt.ack, sizeof(pkt.ack)) < 0)
|
|
+ return;
|
|
+ if (pkt.ack.reason == RXRPC_ACK_PING_RESPONSE)
|
|
+ return;
|
|
+ }
|
|
+
|
|
chan = &conn->channels[sp->hdr.cid & RXRPC_CHANNELMASK];
|
|
|
|
/* If the last call got moved on whilst we were waiting to run, just
|
|
diff --git net/rxrpc/conn_service.c net/rxrpc/conn_service.c
|
|
index f6fcdb3130a1..7c5745997cd4 100644
|
|
--- net/rxrpc/conn_service.c
|
|
+++ net/rxrpc/conn_service.c
|
|
@@ -29,7 +29,7 @@ struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *peer,
|
|
struct rxrpc_conn_proto k;
|
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
|
struct rb_node *p;
|
|
- unsigned int seq = 0;
|
|
+ unsigned int seq = 1;
|
|
|
|
k.epoch = sp->hdr.epoch;
|
|
k.cid = sp->hdr.cid & RXRPC_CIDMASK;
|
|
@@ -39,6 +39,7 @@ struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *peer,
|
|
* under just the RCU read lock, so we have to check for
|
|
* changes.
|
|
*/
|
|
+ seq++; /* 2 on the 1st/lockless path, otherwise odd */
|
|
read_seqbegin_or_lock(&peer->service_conn_lock, &seq);
|
|
|
|
p = rcu_dereference_raw(peer->service_conns.rb_node);
|
|
diff --git net/sched/Kconfig net/sched/Kconfig
|
|
index 782114a230ae..1a3ee928c57c 100644
|
|
--- net/sched/Kconfig
|
|
+++ net/sched/Kconfig
|
|
@@ -44,23 +44,6 @@ if NET_SCHED
|
|
|
|
comment "Queueing/Scheduling"
|
|
|
|
-config NET_SCH_CBQ
|
|
- tristate "Class Based Queueing (CBQ)"
|
|
- ---help---
|
|
- Say Y here if you want to use the Class-Based Queueing (CBQ) packet
|
|
- scheduling algorithm. This algorithm classifies the waiting packets
|
|
- into a tree-like hierarchy of classes; the leaves of this tree are
|
|
- in turn scheduled by separate algorithms.
|
|
-
|
|
- See the top of <file:net/sched/sch_cbq.c> for more details.
|
|
-
|
|
- CBQ is a commonly used scheduler, so if you're unsure, you should
|
|
- say Y here. Then say Y to all the queueing algorithms below that you
|
|
- want to use as leaf disciplines.
|
|
-
|
|
- To compile this code as a module, choose M here: the
|
|
- module will be called sch_cbq.
|
|
-
|
|
config NET_SCH_HTB
|
|
tristate "Hierarchical Token Bucket (HTB)"
|
|
---help---
|
|
@@ -84,20 +67,6 @@ config NET_SCH_HFSC
|
|
To compile this code as a module, choose M here: the
|
|
module will be called sch_hfsc.
|
|
|
|
-config NET_SCH_ATM
|
|
- tristate "ATM Virtual Circuits (ATM)"
|
|
- depends on ATM
|
|
- ---help---
|
|
- Say Y here if you want to use the ATM pseudo-scheduler. This
|
|
- provides a framework for invoking classifiers, which in turn
|
|
- select classes of this queuing discipline. Each class maps
|
|
- the flow(s) it is handling to a given virtual circuit.
|
|
-
|
|
- See the top of <file:net/sched/sch_atm.c> for more details.
|
|
-
|
|
- To compile this code as a module, choose M here: the
|
|
- module will be called sch_atm.
|
|
-
|
|
config NET_SCH_PRIO
|
|
tristate "Multi Band Priority Queueing (PRIO)"
|
|
---help---
|
|
@@ -183,17 +152,6 @@ config NET_SCH_GRED
|
|
To compile this code as a module, choose M here: the
|
|
module will be called sch_gred.
|
|
|
|
-config NET_SCH_DSMARK
|
|
- tristate "Differentiated Services marker (DSMARK)"
|
|
- ---help---
|
|
- Say Y if you want to schedule packets according to the
|
|
- Differentiated Services architecture proposed in RFC 2475.
|
|
- Technical information on this method, with pointers to associated
|
|
- RFCs, is available at <http://www.gta.ufrj.br/diffserv/>.
|
|
-
|
|
- To compile this code as a module, choose M here: the
|
|
- module will be called sch_dsmark.
|
|
-
|
|
config NET_SCH_NETEM
|
|
tristate "Network emulator (NETEM)"
|
|
---help---
|
|
diff --git net/sched/Makefile net/sched/Makefile
|
|
index c156c182f546..b2c2cea1fd91 100644
|
|
--- net/sched/Makefile
|
|
+++ net/sched/Makefile
|
|
@@ -28,20 +28,17 @@ obj-$(CONFIG_NET_IFE_SKBPRIO) += act_meta_skbprio.o
|
|
obj-$(CONFIG_NET_IFE_SKBTCINDEX) += act_meta_skbtcindex.o
|
|
obj-$(CONFIG_NET_ACT_TUNNEL_KEY)+= act_tunnel_key.o
|
|
obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o
|
|
-obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
|
|
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
|
|
obj-$(CONFIG_NET_SCH_HFSC) += sch_hfsc.o
|
|
obj-$(CONFIG_NET_SCH_RED) += sch_red.o
|
|
obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o
|
|
obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
|
|
-obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
|
|
obj-$(CONFIG_NET_SCH_SFB) += sch_sfb.o
|
|
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
|
|
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
|
|
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
|
|
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
|
|
obj-$(CONFIG_NET_SCH_MULTIQ) += sch_multiq.o
|
|
-obj-$(CONFIG_NET_SCH_ATM) += sch_atm.o
|
|
obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o
|
|
obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o
|
|
obj-$(CONFIG_NET_SCH_PLUG) += sch_plug.o
|
|
diff --git net/sched/sch_atm.c net/sched/sch_atm.c
|
|
deleted file mode 100644
|
|
index 184ce9050457..000000000000
|
|
--- net/sched/sch_atm.c
|
|
+++ /dev/null
|
|
@@ -1,701 +0,0 @@
|
|
-/* net/sched/sch_atm.c - ATM VC selection "queueing discipline" */
|
|
-
|
|
-/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
|
|
-
|
|
-#include <linux/module.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/init.h>
|
|
-#include <linux/interrupt.h>
|
|
-#include <linux/string.h>
|
|
-#include <linux/errno.h>
|
|
-#include <linux/skbuff.h>
|
|
-#include <linux/atmdev.h>
|
|
-#include <linux/atmclip.h>
|
|
-#include <linux/rtnetlink.h>
|
|
-#include <linux/file.h> /* for fput */
|
|
-#include <net/netlink.h>
|
|
-#include <net/pkt_sched.h>
|
|
-#include <net/pkt_cls.h>
|
|
-
|
|
-/*
|
|
- * The ATM queuing discipline provides a framework for invoking classifiers
|
|
- * (aka "filters"), which in turn select classes of this queuing discipline.
|
|
- * Each class maps the flow(s) it is handling to a given VC. Multiple classes
|
|
- * may share the same VC.
|
|
- *
|
|
- * When creating a class, VCs are specified by passing the number of the open
|
|
- * socket descriptor by which the calling process references the VC. The kernel
|
|
- * keeps the VC open at least until all classes using it are removed.
|
|
- *
|
|
- * In this file, most functions are named atm_tc_* to avoid confusion with all
|
|
- * the atm_* in net/atm. This naming convention differs from what's used in the
|
|
- * rest of net/sched.
|
|
- *
|
|
- * Known bugs:
|
|
- * - sometimes messes up the IP stack
|
|
- * - any manipulations besides the few operations described in the README, are
|
|
- * untested and likely to crash the system
|
|
- * - should lock the flow while there is data in the queue (?)
|
|
- */
|
|
-
|
|
-#define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back))
|
|
-
|
|
-struct atm_flow_data {
|
|
- struct Qdisc_class_common common;
|
|
- struct Qdisc *q; /* FIFO, TBF, etc. */
|
|
- struct tcf_proto __rcu *filter_list;
|
|
- struct tcf_block *block;
|
|
- struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */
|
|
- void (*old_pop)(struct atm_vcc *vcc,
|
|
- struct sk_buff *skb); /* chaining */
|
|
- struct atm_qdisc_data *parent; /* parent qdisc */
|
|
- struct socket *sock; /* for closing */
|
|
- int ref; /* reference count */
|
|
- struct gnet_stats_basic_packed bstats;
|
|
- struct gnet_stats_queue qstats;
|
|
- struct list_head list;
|
|
- struct atm_flow_data *excess; /* flow for excess traffic;
|
|
- NULL to set CLP instead */
|
|
- int hdr_len;
|
|
- unsigned char hdr[0]; /* header data; MUST BE LAST */
|
|
-};
|
|
-
|
|
-struct atm_qdisc_data {
|
|
- struct atm_flow_data link; /* unclassified skbs go here */
|
|
- struct list_head flows; /* NB: "link" is also on this
|
|
- list */
|
|
- struct tasklet_struct task; /* dequeue tasklet */
|
|
-};
|
|
-
|
|
-/* ------------------------- Class/flow operations ------------------------- */
|
|
-
|
|
-static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow;
|
|
-
|
|
- list_for_each_entry(flow, &p->flows, list) {
|
|
- if (flow->common.classid == classid)
|
|
- return flow;
|
|
- }
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-static int atm_tc_graft(struct Qdisc *sch, unsigned long arg,
|
|
- struct Qdisc *new, struct Qdisc **old)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow = (struct atm_flow_data *)arg;
|
|
-
|
|
- pr_debug("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",
|
|
- sch, p, flow, new, old);
|
|
- if (list_empty(&flow->list))
|
|
- return -EINVAL;
|
|
- if (!new)
|
|
- new = &noop_qdisc;
|
|
- *old = flow->q;
|
|
- flow->q = new;
|
|
- if (*old)
|
|
- qdisc_reset(*old);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static struct Qdisc *atm_tc_leaf(struct Qdisc *sch, unsigned long cl)
|
|
-{
|
|
- struct atm_flow_data *flow = (struct atm_flow_data *)cl;
|
|
-
|
|
- pr_debug("atm_tc_leaf(sch %p,flow %p)\n", sch, flow);
|
|
- return flow ? flow->q : NULL;
|
|
-}
|
|
-
|
|
-static unsigned long atm_tc_find(struct Qdisc *sch, u32 classid)
|
|
-{
|
|
- struct atm_qdisc_data *p __maybe_unused = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow;
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p],classid %x)\n", __func__, sch, p, classid);
|
|
- flow = lookup_flow(sch, classid);
|
|
- pr_debug("%s: flow %p\n", __func__, flow);
|
|
- return (unsigned long)flow;
|
|
-}
|
|
-
|
|
-static unsigned long atm_tc_bind_filter(struct Qdisc *sch,
|
|
- unsigned long parent, u32 classid)
|
|
-{
|
|
- struct atm_qdisc_data *p __maybe_unused = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow;
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p],classid %x)\n", __func__, sch, p, classid);
|
|
- flow = lookup_flow(sch, classid);
|
|
- if (flow)
|
|
- flow->ref++;
|
|
- pr_debug("%s: flow %p\n", __func__, flow);
|
|
- return (unsigned long)flow;
|
|
-}
|
|
-
|
|
-/*
|
|
- * atm_tc_put handles all destructions, including the ones that are explicitly
|
|
- * requested (atm_tc_destroy, etc.). The assumption here is that we never drop
|
|
- * anything that still seems to be in use.
|
|
- */
|
|
-static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow = (struct atm_flow_data *)cl;
|
|
-
|
|
- pr_debug("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
|
|
- if (--flow->ref)
|
|
- return;
|
|
- pr_debug("atm_tc_put: destroying\n");
|
|
- list_del_init(&flow->list);
|
|
- pr_debug("atm_tc_put: qdisc %p\n", flow->q);
|
|
- qdisc_destroy(flow->q);
|
|
- tcf_block_put(flow->block);
|
|
- if (flow->sock) {
|
|
- pr_debug("atm_tc_put: f_count %ld\n",
|
|
- file_count(flow->sock->file));
|
|
- flow->vcc->pop = flow->old_pop;
|
|
- sockfd_put(flow->sock);
|
|
- }
|
|
- if (flow->excess)
|
|
- atm_tc_put(sch, (unsigned long)flow->excess);
|
|
- if (flow != &p->link)
|
|
- kfree(flow);
|
|
- /*
|
|
- * If flow == &p->link, the qdisc no longer works at this point and
|
|
- * needs to be removed. (By the caller of atm_tc_put.)
|
|
- */
|
|
-}
|
|
-
|
|
-static void sch_atm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
|
|
-{
|
|
- struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent;
|
|
-
|
|
- pr_debug("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p);
|
|
- VCC2FLOW(vcc)->old_pop(vcc, skb);
|
|
- tasklet_schedule(&p->task);
|
|
-}
|
|
-
|
|
-static const u8 llc_oui_ip[] = {
|
|
- 0xaa, /* DSAP: non-ISO */
|
|
- 0xaa, /* SSAP: non-ISO */
|
|
- 0x03, /* Ctrl: Unnumbered Information Command PDU */
|
|
- 0x00, /* OUI: EtherType */
|
|
- 0x00, 0x00,
|
|
- 0x08, 0x00
|
|
-}; /* Ethertype IP (0800) */
|
|
-
|
|
-static const struct nla_policy atm_policy[TCA_ATM_MAX + 1] = {
|
|
- [TCA_ATM_FD] = { .type = NLA_U32 },
|
|
- [TCA_ATM_EXCESS] = { .type = NLA_U32 },
|
|
-};
|
|
-
|
|
-static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
|
|
- struct nlattr **tca, unsigned long *arg)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow = (struct atm_flow_data *)*arg;
|
|
- struct atm_flow_data *excess = NULL;
|
|
- struct nlattr *opt = tca[TCA_OPTIONS];
|
|
- struct nlattr *tb[TCA_ATM_MAX + 1];
|
|
- struct socket *sock;
|
|
- int fd, error, hdr_len;
|
|
- void *hdr;
|
|
-
|
|
- pr_debug("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x,"
|
|
- "flow %p,opt %p)\n", sch, p, classid, parent, flow, opt);
|
|
- /*
|
|
- * The concept of parents doesn't apply for this qdisc.
|
|
- */
|
|
- if (parent && parent != TC_H_ROOT && parent != sch->handle)
|
|
- return -EINVAL;
|
|
- /*
|
|
- * ATM classes cannot be changed. In order to change properties of the
|
|
- * ATM connection, that socket needs to be modified directly (via the
|
|
- * native ATM API. In order to send a flow to a different VC, the old
|
|
- * class needs to be removed and a new one added. (This may be changed
|
|
- * later.)
|
|
- */
|
|
- if (flow)
|
|
- return -EBUSY;
|
|
- if (opt == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- error = nla_parse_nested(tb, TCA_ATM_MAX, opt, atm_policy, NULL);
|
|
- if (error < 0)
|
|
- return error;
|
|
-
|
|
- if (!tb[TCA_ATM_FD])
|
|
- return -EINVAL;
|
|
- fd = nla_get_u32(tb[TCA_ATM_FD]);
|
|
- pr_debug("atm_tc_change: fd %d\n", fd);
|
|
- if (tb[TCA_ATM_HDR]) {
|
|
- hdr_len = nla_len(tb[TCA_ATM_HDR]);
|
|
- hdr = nla_data(tb[TCA_ATM_HDR]);
|
|
- } else {
|
|
- hdr_len = RFC1483LLC_LEN;
|
|
- hdr = NULL; /* default LLC/SNAP for IP */
|
|
- }
|
|
- if (!tb[TCA_ATM_EXCESS])
|
|
- excess = NULL;
|
|
- else {
|
|
- excess = (struct atm_flow_data *)
|
|
- atm_tc_find(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
|
|
- if (!excess)
|
|
- return -ENOENT;
|
|
- }
|
|
- pr_debug("atm_tc_change: type %d, payload %d, hdr_len %d\n",
|
|
- opt->nla_type, nla_len(opt), hdr_len);
|
|
- sock = sockfd_lookup(fd, &error);
|
|
- if (!sock)
|
|
- return error; /* f_count++ */
|
|
- pr_debug("atm_tc_change: f_count %ld\n", file_count(sock->file));
|
|
- if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
|
|
- error = -EPROTOTYPE;
|
|
- goto err_out;
|
|
- }
|
|
- /* @@@ should check if the socket is really operational or we'll crash
|
|
- on vcc->send */
|
|
- if (classid) {
|
|
- if (TC_H_MAJ(classid ^ sch->handle)) {
|
|
- pr_debug("atm_tc_change: classid mismatch\n");
|
|
- error = -EINVAL;
|
|
- goto err_out;
|
|
- }
|
|
- } else {
|
|
- int i;
|
|
- unsigned long cl;
|
|
-
|
|
- for (i = 1; i < 0x8000; i++) {
|
|
- classid = TC_H_MAKE(sch->handle, 0x8000 | i);
|
|
- cl = atm_tc_find(sch, classid);
|
|
- if (!cl)
|
|
- break;
|
|
- }
|
|
- }
|
|
- pr_debug("atm_tc_change: new id %x\n", classid);
|
|
- flow = kzalloc(sizeof(struct atm_flow_data) + hdr_len, GFP_KERNEL);
|
|
- pr_debug("atm_tc_change: flow %p\n", flow);
|
|
- if (!flow) {
|
|
- error = -ENOBUFS;
|
|
- goto err_out;
|
|
- }
|
|
-
|
|
- error = tcf_block_get(&flow->block, &flow->filter_list);
|
|
- if (error) {
|
|
- kfree(flow);
|
|
- goto err_out;
|
|
- }
|
|
-
|
|
- flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
|
|
- if (!flow->q)
|
|
- flow->q = &noop_qdisc;
|
|
- pr_debug("atm_tc_change: qdisc %p\n", flow->q);
|
|
- flow->sock = sock;
|
|
- flow->vcc = ATM_SD(sock); /* speedup */
|
|
- flow->vcc->user_back = flow;
|
|
- pr_debug("atm_tc_change: vcc %p\n", flow->vcc);
|
|
- flow->old_pop = flow->vcc->pop;
|
|
- flow->parent = p;
|
|
- flow->vcc->pop = sch_atm_pop;
|
|
- flow->common.classid = classid;
|
|
- flow->ref = 1;
|
|
- flow->excess = excess;
|
|
- list_add(&flow->list, &p->link.list);
|
|
- flow->hdr_len = hdr_len;
|
|
- if (hdr)
|
|
- memcpy(flow->hdr, hdr, hdr_len);
|
|
- else
|
|
- memcpy(flow->hdr, llc_oui_ip, sizeof(llc_oui_ip));
|
|
- *arg = (unsigned long)flow;
|
|
- return 0;
|
|
-err_out:
|
|
- sockfd_put(sock);
|
|
- return error;
|
|
-}
|
|
-
|
|
-static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow = (struct atm_flow_data *)arg;
|
|
-
|
|
- pr_debug("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
|
|
- if (list_empty(&flow->list))
|
|
- return -EINVAL;
|
|
- if (rcu_access_pointer(flow->filter_list) || flow == &p->link)
|
|
- return -EBUSY;
|
|
- /*
|
|
- * Reference count must be 2: one for "keepalive" (set at class
|
|
- * creation), and one for the reference held when calling delete.
|
|
- */
|
|
- if (flow->ref < 2) {
|
|
- pr_err("atm_tc_delete: flow->ref == %d\n", flow->ref);
|
|
- return -EINVAL;
|
|
- }
|
|
- if (flow->ref > 2)
|
|
- return -EBUSY; /* catch references via excess, etc. */
|
|
- atm_tc_put(sch, arg);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow;
|
|
-
|
|
- pr_debug("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
|
|
- if (walker->stop)
|
|
- return;
|
|
- list_for_each_entry(flow, &p->flows, list) {
|
|
- if (walker->count >= walker->skip &&
|
|
- walker->fn(sch, (unsigned long)flow, walker) < 0) {
|
|
- walker->stop = 1;
|
|
- break;
|
|
- }
|
|
- walker->count++;
|
|
- }
|
|
-}
|
|
-
|
|
-static struct tcf_block *atm_tc_tcf_block(struct Qdisc *sch, unsigned long cl)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow = (struct atm_flow_data *)cl;
|
|
-
|
|
- pr_debug("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
|
|
- return flow ? flow->block : p->link.block;
|
|
-}
|
|
-
|
|
-/* --------------------------- Qdisc operations ---------------------------- */
|
|
-
|
|
-static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|
- struct sk_buff **to_free)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow;
|
|
- struct tcf_result res;
|
|
- int result;
|
|
- int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
|
|
-
|
|
- pr_debug("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
|
|
- result = TC_ACT_OK; /* be nice to gcc */
|
|
- flow = NULL;
|
|
- if (TC_H_MAJ(skb->priority) != sch->handle ||
|
|
- !(flow = (struct atm_flow_data *)atm_tc_find(sch, skb->priority))) {
|
|
- struct tcf_proto *fl;
|
|
-
|
|
- list_for_each_entry(flow, &p->flows, list) {
|
|
- fl = rcu_dereference_bh(flow->filter_list);
|
|
- if (fl) {
|
|
- result = tcf_classify(skb, fl, &res, true);
|
|
- if (result < 0)
|
|
- continue;
|
|
- if (result == TC_ACT_SHOT)
|
|
- goto done;
|
|
-
|
|
- flow = (struct atm_flow_data *)res.class;
|
|
- if (!flow)
|
|
- flow = lookup_flow(sch, res.classid);
|
|
- goto drop;
|
|
- }
|
|
- }
|
|
- flow = NULL;
|
|
-done:
|
|
- ;
|
|
- }
|
|
- if (!flow) {
|
|
- flow = &p->link;
|
|
- } else {
|
|
- if (flow->vcc)
|
|
- ATM_SKB(skb)->atm_options = flow->vcc->atm_options;
|
|
- /*@@@ looks good ... but it's not supposed to work :-) */
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
- switch (result) {
|
|
- case TC_ACT_QUEUED:
|
|
- case TC_ACT_STOLEN:
|
|
- case TC_ACT_TRAP:
|
|
- __qdisc_drop(skb, to_free);
|
|
- return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
|
|
- case TC_ACT_SHOT:
|
|
- __qdisc_drop(skb, to_free);
|
|
- goto drop;
|
|
- case TC_ACT_RECLASSIFY:
|
|
- if (flow->excess)
|
|
- flow = flow->excess;
|
|
- else
|
|
- ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP;
|
|
- break;
|
|
- }
|
|
-#endif
|
|
- }
|
|
-
|
|
- ret = qdisc_enqueue(skb, flow->q, to_free);
|
|
- if (ret != NET_XMIT_SUCCESS) {
|
|
-drop: __maybe_unused
|
|
- if (net_xmit_drop_count(ret)) {
|
|
- qdisc_qstats_drop(sch);
|
|
- if (flow)
|
|
- flow->qstats.drops++;
|
|
- }
|
|
- return ret;
|
|
- }
|
|
- /*
|
|
- * Okay, this may seem weird. We pretend we've dropped the packet if
|
|
- * it goes via ATM. The reason for this is that the outer qdisc
|
|
- * expects to be able to q->dequeue the packet later on if we return
|
|
- * success at this place. Also, sch->q.qdisc needs to reflect whether
|
|
- * there is a packet egligible for dequeuing or not. Note that the
|
|
- * statistics of the outer qdisc are necessarily wrong because of all
|
|
- * this. There's currently no correct solution for this.
|
|
- */
|
|
- if (flow == &p->link) {
|
|
- sch->q.qlen++;
|
|
- return NET_XMIT_SUCCESS;
|
|
- }
|
|
- tasklet_schedule(&p->task);
|
|
- return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Dequeue packets and send them over ATM. Note that we quite deliberately
|
|
- * avoid checking net_device's flow control here, simply because sch_atm
|
|
- * uses its own channels, which have nothing to do with any CLIP/LANE/or
|
|
- * non-ATM interfaces.
|
|
- */
|
|
-
|
|
-static void sch_atm_dequeue(unsigned long data)
|
|
-{
|
|
- struct Qdisc *sch = (struct Qdisc *)data;
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow;
|
|
- struct sk_buff *skb;
|
|
-
|
|
- pr_debug("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p);
|
|
- list_for_each_entry(flow, &p->flows, list) {
|
|
- if (flow == &p->link)
|
|
- continue;
|
|
- /*
|
|
- * If traffic is properly shaped, this won't generate nasty
|
|
- * little bursts. Otherwise, it may ... (but that's okay)
|
|
- */
|
|
- while ((skb = flow->q->ops->peek(flow->q))) {
|
|
- if (!atm_may_send(flow->vcc, skb->truesize))
|
|
- break;
|
|
-
|
|
- skb = qdisc_dequeue_peeked(flow->q);
|
|
- if (unlikely(!skb))
|
|
- break;
|
|
-
|
|
- qdisc_bstats_update(sch, skb);
|
|
- bstats_update(&flow->bstats, skb);
|
|
- pr_debug("atm_tc_dequeue: sending on class %p\n", flow);
|
|
- /* remove any LL header somebody else has attached */
|
|
- skb_pull(skb, skb_network_offset(skb));
|
|
- if (skb_headroom(skb) < flow->hdr_len) {
|
|
- struct sk_buff *new;
|
|
-
|
|
- new = skb_realloc_headroom(skb, flow->hdr_len);
|
|
- dev_kfree_skb(skb);
|
|
- if (!new)
|
|
- continue;
|
|
- skb = new;
|
|
- }
|
|
- pr_debug("sch_atm_dequeue: ip %p, data %p\n",
|
|
- skb_network_header(skb), skb->data);
|
|
- ATM_SKB(skb)->vcc = flow->vcc;
|
|
- memcpy(skb_push(skb, flow->hdr_len), flow->hdr,
|
|
- flow->hdr_len);
|
|
- refcount_add(skb->truesize,
|
|
- &sk_atm(flow->vcc)->sk_wmem_alloc);
|
|
- /* atm.atm_options are already set by atm_tc_enqueue */
|
|
- flow->vcc->send(flow->vcc, skb);
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct sk_buff *skb;
|
|
-
|
|
- pr_debug("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p);
|
|
- tasklet_schedule(&p->task);
|
|
- skb = qdisc_dequeue_peeked(p->link.q);
|
|
- if (skb)
|
|
- sch->q.qlen--;
|
|
- return skb;
|
|
-}
|
|
-
|
|
-static struct sk_buff *atm_tc_peek(struct Qdisc *sch)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
-
|
|
- pr_debug("atm_tc_peek(sch %p,[qdisc %p])\n", sch, p);
|
|
-
|
|
- return p->link.q->ops->peek(p->link.q);
|
|
-}
|
|
-
|
|
-static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- int err;
|
|
-
|
|
- pr_debug("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
|
|
- INIT_LIST_HEAD(&p->flows);
|
|
- INIT_LIST_HEAD(&p->link.list);
|
|
- list_add(&p->link.list, &p->flows);
|
|
- p->link.q = qdisc_create_dflt(sch->dev_queue,
|
|
- &pfifo_qdisc_ops, sch->handle);
|
|
- if (!p->link.q)
|
|
- p->link.q = &noop_qdisc;
|
|
- pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
|
|
- p->link.vcc = NULL;
|
|
- p->link.sock = NULL;
|
|
- p->link.common.classid = sch->handle;
|
|
- p->link.ref = 1;
|
|
-
|
|
- err = tcf_block_get(&p->link.block, &p->link.filter_list);
|
|
- if (err)
|
|
- return err;
|
|
-
|
|
- tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void atm_tc_reset(struct Qdisc *sch)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow;
|
|
-
|
|
- pr_debug("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
|
|
- list_for_each_entry(flow, &p->flows, list)
|
|
- qdisc_reset(flow->q);
|
|
- sch->q.qlen = 0;
|
|
-}
|
|
-
|
|
-static void atm_tc_destroy(struct Qdisc *sch)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow, *tmp;
|
|
-
|
|
- pr_debug("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
|
|
- list_for_each_entry(flow, &p->flows, list) {
|
|
- tcf_block_put(flow->block);
|
|
- flow->block = NULL;
|
|
- }
|
|
-
|
|
- list_for_each_entry_safe(flow, tmp, &p->flows, list) {
|
|
- if (flow->ref > 1)
|
|
- pr_err("atm_destroy: %p->ref = %d\n", flow, flow->ref);
|
|
- atm_tc_put(sch, (unsigned long)flow);
|
|
- }
|
|
- tasklet_kill(&p->task);
|
|
-}
|
|
-
|
|
-static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
|
|
- struct sk_buff *skb, struct tcmsg *tcm)
|
|
-{
|
|
- struct atm_qdisc_data *p = qdisc_priv(sch);
|
|
- struct atm_flow_data *flow = (struct atm_flow_data *)cl;
|
|
- struct nlattr *nest;
|
|
-
|
|
- pr_debug("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
|
|
- sch, p, flow, skb, tcm);
|
|
- if (list_empty(&flow->list))
|
|
- return -EINVAL;
|
|
- tcm->tcm_handle = flow->common.classid;
|
|
- tcm->tcm_info = flow->q->handle;
|
|
-
|
|
- nest = nla_nest_start(skb, TCA_OPTIONS);
|
|
- if (nest == NULL)
|
|
- goto nla_put_failure;
|
|
-
|
|
- if (nla_put(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr))
|
|
- goto nla_put_failure;
|
|
- if (flow->vcc) {
|
|
- struct sockaddr_atmpvc pvc;
|
|
- int state;
|
|
-
|
|
- memset(&pvc, 0, sizeof(pvc));
|
|
- pvc.sap_family = AF_ATMPVC;
|
|
- pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1;
|
|
- pvc.sap_addr.vpi = flow->vcc->vpi;
|
|
- pvc.sap_addr.vci = flow->vcc->vci;
|
|
- if (nla_put(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc))
|
|
- goto nla_put_failure;
|
|
- state = ATM_VF2VS(flow->vcc->flags);
|
|
- if (nla_put_u32(skb, TCA_ATM_STATE, state))
|
|
- goto nla_put_failure;
|
|
- }
|
|
- if (flow->excess) {
|
|
- if (nla_put_u32(skb, TCA_ATM_EXCESS, flow->common.classid))
|
|
- goto nla_put_failure;
|
|
- } else {
|
|
- if (nla_put_u32(skb, TCA_ATM_EXCESS, 0))
|
|
- goto nla_put_failure;
|
|
- }
|
|
- return nla_nest_end(skb, nest);
|
|
-
|
|
-nla_put_failure:
|
|
- nla_nest_cancel(skb, nest);
|
|
- return -1;
|
|
-}
|
|
-static int
|
|
-atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
|
|
- struct gnet_dump *d)
|
|
-{
|
|
- struct atm_flow_data *flow = (struct atm_flow_data *)arg;
|
|
-
|
|
- if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
|
|
- d, NULL, &flow->bstats) < 0 ||
|
|
- gnet_stats_copy_queue(d, NULL, &flow->qstats, flow->q->q.qlen) < 0)
|
|
- return -1;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static const struct Qdisc_class_ops atm_class_ops = {
|
|
- .graft = atm_tc_graft,
|
|
- .leaf = atm_tc_leaf,
|
|
- .find = atm_tc_find,
|
|
- .change = atm_tc_change,
|
|
- .delete = atm_tc_delete,
|
|
- .walk = atm_tc_walk,
|
|
- .tcf_block = atm_tc_tcf_block,
|
|
- .bind_tcf = atm_tc_bind_filter,
|
|
- .unbind_tcf = atm_tc_put,
|
|
- .dump = atm_tc_dump_class,
|
|
- .dump_stats = atm_tc_dump_class_stats,
|
|
-};
|
|
-
|
|
-static struct Qdisc_ops atm_qdisc_ops __read_mostly = {
|
|
- .cl_ops = &atm_class_ops,
|
|
- .id = "atm",
|
|
- .priv_size = sizeof(struct atm_qdisc_data),
|
|
- .enqueue = atm_tc_enqueue,
|
|
- .dequeue = atm_tc_dequeue,
|
|
- .peek = atm_tc_peek,
|
|
- .init = atm_tc_init,
|
|
- .reset = atm_tc_reset,
|
|
- .destroy = atm_tc_destroy,
|
|
- .dump = atm_tc_dump,
|
|
- .owner = THIS_MODULE,
|
|
-};
|
|
-
|
|
-static int __init atm_init(void)
|
|
-{
|
|
- return register_qdisc(&atm_qdisc_ops);
|
|
-}
|
|
-
|
|
-static void __exit atm_exit(void)
|
|
-{
|
|
- unregister_qdisc(&atm_qdisc_ops);
|
|
-}
|
|
-
|
|
-module_init(atm_init)
|
|
-module_exit(atm_exit)
|
|
-MODULE_LICENSE("GPL");
|
|
diff --git net/sched/sch_cbq.c net/sched/sch_cbq.c
|
|
deleted file mode 100644
|
|
index 92ff508367e8..000000000000
|
|
--- net/sched/sch_cbq.c
|
|
+++ /dev/null
|
|
@@ -1,1794 +0,0 @@
|
|
-/*
|
|
- * net/sched/sch_cbq.c Class-Based Queueing discipline.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * as published by the Free Software Foundation; either version
|
|
- * 2 of the License, or (at your option) any later version.
|
|
- *
|
|
- * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
|
- *
|
|
- */
|
|
-
|
|
-#include <linux/module.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/types.h>
|
|
-#include <linux/kernel.h>
|
|
-#include <linux/string.h>
|
|
-#include <linux/errno.h>
|
|
-#include <linux/skbuff.h>
|
|
-#include <net/netlink.h>
|
|
-#include <net/pkt_sched.h>
|
|
-#include <net/pkt_cls.h>
|
|
-
|
|
-
|
|
-/* Class-Based Queueing (CBQ) algorithm.
|
|
- =======================================
|
|
-
|
|
- Sources: [1] Sally Floyd and Van Jacobson, "Link-sharing and Resource
|
|
- Management Models for Packet Networks",
|
|
- IEEE/ACM Transactions on Networking, Vol.3, No.4, 1995
|
|
-
|
|
- [2] Sally Floyd, "Notes on CBQ and Guaranteed Service", 1995
|
|
-
|
|
- [3] Sally Floyd, "Notes on Class-Based Queueing: Setting
|
|
- Parameters", 1996
|
|
-
|
|
- [4] Sally Floyd and Michael Speer, "Experimental Results
|
|
- for Class-Based Queueing", 1998, not published.
|
|
-
|
|
- -----------------------------------------------------------------------
|
|
-
|
|
- Algorithm skeleton was taken from NS simulator cbq.cc.
|
|
- If someone wants to check this code against the LBL version,
|
|
- he should take into account that ONLY the skeleton was borrowed,
|
|
- the implementation is different. Particularly:
|
|
-
|
|
- --- The WRR algorithm is different. Our version looks more
|
|
- reasonable (I hope) and works when quanta are allowed to be
|
|
- less than MTU, which is always the case when real time classes
|
|
- have small rates. Note, that the statement of [3] is
|
|
- incomplete, delay may actually be estimated even if class
|
|
- per-round allotment is less than MTU. Namely, if per-round
|
|
- allotment is W*r_i, and r_1+...+r_k = r < 1
|
|
-
|
|
- delay_i <= ([MTU/(W*r_i)]*W*r + W*r + k*MTU)/B
|
|
-
|
|
- In the worst case we have IntServ estimate with D = W*r+k*MTU
|
|
- and C = MTU*r. The proof (if correct at all) is trivial.
|
|
-
|
|
-
|
|
- --- It seems that cbq-2.0 is not very accurate. At least, I cannot
|
|
- interpret some places, which look like wrong translations
|
|
- from NS. Anyone is advised to find these differences
|
|
- and explain to me, why I am wrong 8).
|
|
-
|
|
- --- Linux has no EOI event, so that we cannot estimate true class
|
|
- idle time. Workaround is to consider the next dequeue event
|
|
- as sign that previous packet is finished. This is wrong because of
|
|
- internal device queueing, but on a permanently loaded link it is true.
|
|
- Moreover, combined with clock integrator, this scheme looks
|
|
- very close to an ideal solution. */
|
|
-
|
|
-struct cbq_sched_data;
|
|
-
|
|
-
|
|
-struct cbq_class {
|
|
- struct Qdisc_class_common common;
|
|
- struct cbq_class *next_alive; /* next class with backlog in this priority band */
|
|
-
|
|
-/* Parameters */
|
|
- unsigned char priority; /* class priority */
|
|
- unsigned char priority2; /* priority to be used after overlimit */
|
|
- unsigned char ewma_log; /* time constant for idle time calculation */
|
|
-
|
|
- u32 defmap;
|
|
-
|
|
- /* Link-sharing scheduler parameters */
|
|
- long maxidle; /* Class parameters: see below. */
|
|
- long offtime;
|
|
- long minidle;
|
|
- u32 avpkt;
|
|
- struct qdisc_rate_table *R_tab;
|
|
-
|
|
- /* General scheduler (WRR) parameters */
|
|
- long allot;
|
|
- long quantum; /* Allotment per WRR round */
|
|
- long weight; /* Relative allotment: see below */
|
|
-
|
|
- struct Qdisc *qdisc; /* Ptr to CBQ discipline */
|
|
- struct cbq_class *split; /* Ptr to split node */
|
|
- struct cbq_class *share; /* Ptr to LS parent in the class tree */
|
|
- struct cbq_class *tparent; /* Ptr to tree parent in the class tree */
|
|
- struct cbq_class *borrow; /* NULL if class is bandwidth limited;
|
|
- parent otherwise */
|
|
- struct cbq_class *sibling; /* Sibling chain */
|
|
- struct cbq_class *children; /* Pointer to children chain */
|
|
-
|
|
- struct Qdisc *q; /* Elementary queueing discipline */
|
|
-
|
|
-
|
|
-/* Variables */
|
|
- unsigned char cpriority; /* Effective priority */
|
|
- unsigned char delayed;
|
|
- unsigned char level; /* level of the class in hierarchy:
|
|
- 0 for leaf classes, and maximal
|
|
- level of children + 1 for nodes.
|
|
- */
|
|
-
|
|
- psched_time_t last; /* Last end of service */
|
|
- psched_time_t undertime;
|
|
- long avgidle;
|
|
- long deficit; /* Saved deficit for WRR */
|
|
- psched_time_t penalized;
|
|
- struct gnet_stats_basic_packed bstats;
|
|
- struct gnet_stats_queue qstats;
|
|
- struct net_rate_estimator __rcu *rate_est;
|
|
- struct tc_cbq_xstats xstats;
|
|
-
|
|
- struct tcf_proto __rcu *filter_list;
|
|
- struct tcf_block *block;
|
|
-
|
|
- int filters;
|
|
-
|
|
- struct cbq_class *defaults[TC_PRIO_MAX + 1];
|
|
-};
|
|
-
|
|
-struct cbq_sched_data {
|
|
- struct Qdisc_class_hash clhash; /* Hash table of all classes */
|
|
- int nclasses[TC_CBQ_MAXPRIO + 1];
|
|
- unsigned int quanta[TC_CBQ_MAXPRIO + 1];
|
|
-
|
|
- struct cbq_class link;
|
|
-
|
|
- unsigned int activemask;
|
|
- struct cbq_class *active[TC_CBQ_MAXPRIO + 1]; /* List of all classes
|
|
- with backlog */
|
|
-
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
- struct cbq_class *rx_class;
|
|
-#endif
|
|
- struct cbq_class *tx_class;
|
|
- struct cbq_class *tx_borrowed;
|
|
- int tx_len;
|
|
- psched_time_t now; /* Cached timestamp */
|
|
- unsigned int pmask;
|
|
-
|
|
- struct hrtimer delay_timer;
|
|
- struct qdisc_watchdog watchdog; /* Watchdog timer,
|
|
- started when CBQ has
|
|
- backlog, but cannot
|
|
- transmit just now */
|
|
- psched_tdiff_t wd_expires;
|
|
- int toplevel;
|
|
- u32 hgenerator;
|
|
-};
|
|
-
|
|
-
|
|
-#define L2T(cl, len) qdisc_l2t((cl)->R_tab, len)
|
|
-
|
|
-static inline struct cbq_class *
|
|
-cbq_class_lookup(struct cbq_sched_data *q, u32 classid)
|
|
-{
|
|
- struct Qdisc_class_common *clc;
|
|
-
|
|
- clc = qdisc_class_find(&q->clhash, classid);
|
|
- if (clc == NULL)
|
|
- return NULL;
|
|
- return container_of(clc, struct cbq_class, common);
|
|
-}
|
|
-
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
-
|
|
-static struct cbq_class *
|
|
-cbq_reclassify(struct sk_buff *skb, struct cbq_class *this)
|
|
-{
|
|
- struct cbq_class *cl;
|
|
-
|
|
- for (cl = this->tparent; cl; cl = cl->tparent) {
|
|
- struct cbq_class *new = cl->defaults[TC_PRIO_BESTEFFORT];
|
|
-
|
|
- if (new != NULL && new != this)
|
|
- return new;
|
|
- }
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-#endif
|
|
-
|
|
-/* Classify packet. The procedure is pretty complicated, but
|
|
- * it allows us to combine link sharing and priority scheduling
|
|
- * transparently.
|
|
- *
|
|
- * Namely, you can put link sharing rules (f.e. route based) at root of CBQ,
|
|
- * so that it resolves to split nodes. Then packets are classified
|
|
- * by logical priority, or a more specific classifier may be attached
|
|
- * to the split node.
|
|
- */
|
|
-
|
|
-static struct cbq_class *
|
|
-cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *head = &q->link;
|
|
- struct cbq_class **defmap;
|
|
- struct cbq_class *cl = NULL;
|
|
- u32 prio = skb->priority;
|
|
- struct tcf_proto *fl;
|
|
- struct tcf_result res;
|
|
-
|
|
- /*
|
|
- * Step 1. If skb->priority points to one of our classes, use it.
|
|
- */
|
|
- if (TC_H_MAJ(prio ^ sch->handle) == 0 &&
|
|
- (cl = cbq_class_lookup(q, prio)) != NULL)
|
|
- return cl;
|
|
-
|
|
- *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
|
|
- for (;;) {
|
|
- int result = 0;
|
|
- defmap = head->defaults;
|
|
-
|
|
- fl = rcu_dereference_bh(head->filter_list);
|
|
- /*
|
|
- * Step 2+n. Apply classifier.
|
|
- */
|
|
- result = tcf_classify(skb, fl, &res, true);
|
|
- if (!fl || result < 0)
|
|
- goto fallback;
|
|
- if (result == TC_ACT_SHOT)
|
|
- return NULL;
|
|
-
|
|
- cl = (void *)res.class;
|
|
- if (!cl) {
|
|
- if (TC_H_MAJ(res.classid))
|
|
- cl = cbq_class_lookup(q, res.classid);
|
|
- else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL)
|
|
- cl = defmap[TC_PRIO_BESTEFFORT];
|
|
-
|
|
- if (cl == NULL)
|
|
- goto fallback;
|
|
- }
|
|
- if (cl->level >= head->level)
|
|
- goto fallback;
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
- switch (result) {
|
|
- case TC_ACT_QUEUED:
|
|
- case TC_ACT_STOLEN:
|
|
- case TC_ACT_TRAP:
|
|
- *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
|
|
- case TC_ACT_RECLASSIFY:
|
|
- return cbq_reclassify(skb, cl);
|
|
- }
|
|
-#endif
|
|
- if (cl->level == 0)
|
|
- return cl;
|
|
-
|
|
- /*
|
|
- * Step 3+n. If classifier selected a link sharing class,
|
|
- * apply agency specific classifier.
|
|
- * Repeat this procdure until we hit a leaf node.
|
|
- */
|
|
- head = cl;
|
|
- }
|
|
-
|
|
-fallback:
|
|
- cl = head;
|
|
-
|
|
- /*
|
|
- * Step 4. No success...
|
|
- */
|
|
- if (TC_H_MAJ(prio) == 0 &&
|
|
- !(cl = head->defaults[prio & TC_PRIO_MAX]) &&
|
|
- !(cl = head->defaults[TC_PRIO_BESTEFFORT]))
|
|
- return head;
|
|
-
|
|
- return cl;
|
|
-}
|
|
-
|
|
-/*
|
|
- * A packet has just been enqueued on the empty class.
|
|
- * cbq_activate_class adds it to the tail of active class list
|
|
- * of its priority band.
|
|
- */
|
|
-
|
|
-static inline void cbq_activate_class(struct cbq_class *cl)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
- int prio = cl->cpriority;
|
|
- struct cbq_class *cl_tail;
|
|
-
|
|
- cl_tail = q->active[prio];
|
|
- q->active[prio] = cl;
|
|
-
|
|
- if (cl_tail != NULL) {
|
|
- cl->next_alive = cl_tail->next_alive;
|
|
- cl_tail->next_alive = cl;
|
|
- } else {
|
|
- cl->next_alive = cl;
|
|
- q->activemask |= (1<<prio);
|
|
- }
|
|
-}
|
|
-
|
|
-/*
|
|
- * Unlink class from active chain.
|
|
- * Note that this same procedure is done directly in cbq_dequeue*
|
|
- * during round-robin procedure.
|
|
- */
|
|
-
|
|
-static void cbq_deactivate_class(struct cbq_class *this)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(this->qdisc);
|
|
- int prio = this->cpriority;
|
|
- struct cbq_class *cl;
|
|
- struct cbq_class *cl_prev = q->active[prio];
|
|
-
|
|
- do {
|
|
- cl = cl_prev->next_alive;
|
|
- if (cl == this) {
|
|
- cl_prev->next_alive = cl->next_alive;
|
|
- cl->next_alive = NULL;
|
|
-
|
|
- if (cl == q->active[prio]) {
|
|
- q->active[prio] = cl_prev;
|
|
- if (cl == q->active[prio]) {
|
|
- q->active[prio] = NULL;
|
|
- q->activemask &= ~(1<<prio);
|
|
- return;
|
|
- }
|
|
- }
|
|
- return;
|
|
- }
|
|
- } while ((cl_prev = cl) != q->active[prio]);
|
|
-}
|
|
-
|
|
-static void
|
|
-cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)
|
|
-{
|
|
- int toplevel = q->toplevel;
|
|
-
|
|
- if (toplevel > cl->level) {
|
|
- psched_time_t now = psched_get_time();
|
|
-
|
|
- do {
|
|
- if (cl->undertime < now) {
|
|
- q->toplevel = cl->level;
|
|
- return;
|
|
- }
|
|
- } while ((cl = cl->borrow) != NULL && toplevel > cl->level);
|
|
- }
|
|
-}
|
|
-
|
|
-static int
|
|
-cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|
- struct sk_buff **to_free)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- int ret;
|
|
- struct cbq_class *cl = cbq_classify(skb, sch, &ret);
|
|
-
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
- q->rx_class = cl;
|
|
-#endif
|
|
- if (cl == NULL) {
|
|
- if (ret & __NET_XMIT_BYPASS)
|
|
- qdisc_qstats_drop(sch);
|
|
- __qdisc_drop(skb, to_free);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- ret = qdisc_enqueue(skb, cl->q, to_free);
|
|
- if (ret == NET_XMIT_SUCCESS) {
|
|
- sch->q.qlen++;
|
|
- cbq_mark_toplevel(q, cl);
|
|
- if (!cl->next_alive)
|
|
- cbq_activate_class(cl);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- if (net_xmit_drop_count(ret)) {
|
|
- qdisc_qstats_drop(sch);
|
|
- cbq_mark_toplevel(q, cl);
|
|
- cl->qstats.drops++;
|
|
- }
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/* Overlimit action: penalize leaf class by adding offtime */
|
|
-static void cbq_overlimit(struct cbq_class *cl)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
- psched_tdiff_t delay = cl->undertime - q->now;
|
|
-
|
|
- if (!cl->delayed) {
|
|
- delay += cl->offtime;
|
|
-
|
|
- /*
|
|
- * Class goes to sleep, so that it will have no
|
|
- * chance to work avgidle. Let's forgive it 8)
|
|
- *
|
|
- * BTW cbq-2.0 has a crap in this
|
|
- * place, apparently they forgot to shift it by cl->ewma_log.
|
|
- */
|
|
- if (cl->avgidle < 0)
|
|
- delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log);
|
|
- if (cl->avgidle < cl->minidle)
|
|
- cl->avgidle = cl->minidle;
|
|
- if (delay <= 0)
|
|
- delay = 1;
|
|
- cl->undertime = q->now + delay;
|
|
-
|
|
- cl->xstats.overactions++;
|
|
- cl->delayed = 1;
|
|
- }
|
|
- if (q->wd_expires == 0 || q->wd_expires > delay)
|
|
- q->wd_expires = delay;
|
|
-
|
|
- /* Dirty work! We must schedule wakeups based on
|
|
- * real available rate, rather than leaf rate,
|
|
- * which may be tiny (even zero).
|
|
- */
|
|
- if (q->toplevel == TC_CBQ_MAXLEVEL) {
|
|
- struct cbq_class *b;
|
|
- psched_tdiff_t base_delay = q->wd_expires;
|
|
-
|
|
- for (b = cl->borrow; b; b = b->borrow) {
|
|
- delay = b->undertime - q->now;
|
|
- if (delay < base_delay) {
|
|
- if (delay <= 0)
|
|
- delay = 1;
|
|
- base_delay = delay;
|
|
- }
|
|
- }
|
|
-
|
|
- q->wd_expires = base_delay;
|
|
- }
|
|
-}
|
|
-
|
|
-static psched_tdiff_t cbq_undelay_prio(struct cbq_sched_data *q, int prio,
|
|
- psched_time_t now)
|
|
-{
|
|
- struct cbq_class *cl;
|
|
- struct cbq_class *cl_prev = q->active[prio];
|
|
- psched_time_t sched = now;
|
|
-
|
|
- if (cl_prev == NULL)
|
|
- return 0;
|
|
-
|
|
- do {
|
|
- cl = cl_prev->next_alive;
|
|
- if (now - cl->penalized > 0) {
|
|
- cl_prev->next_alive = cl->next_alive;
|
|
- cl->next_alive = NULL;
|
|
- cl->cpriority = cl->priority;
|
|
- cl->delayed = 0;
|
|
- cbq_activate_class(cl);
|
|
-
|
|
- if (cl == q->active[prio]) {
|
|
- q->active[prio] = cl_prev;
|
|
- if (cl == q->active[prio]) {
|
|
- q->active[prio] = NULL;
|
|
- return 0;
|
|
- }
|
|
- }
|
|
-
|
|
- cl = cl_prev->next_alive;
|
|
- } else if (sched - cl->penalized > 0)
|
|
- sched = cl->penalized;
|
|
- } while ((cl_prev = cl) != q->active[prio]);
|
|
-
|
|
- return sched - now;
|
|
-}
|
|
-
|
|
-static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
|
|
-{
|
|
- struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data,
|
|
- delay_timer);
|
|
- struct Qdisc *sch = q->watchdog.qdisc;
|
|
- psched_time_t now;
|
|
- psched_tdiff_t delay = 0;
|
|
- unsigned int pmask;
|
|
-
|
|
- now = psched_get_time();
|
|
-
|
|
- pmask = q->pmask;
|
|
- q->pmask = 0;
|
|
-
|
|
- while (pmask) {
|
|
- int prio = ffz(~pmask);
|
|
- psched_tdiff_t tmp;
|
|
-
|
|
- pmask &= ~(1<<prio);
|
|
-
|
|
- tmp = cbq_undelay_prio(q, prio, now);
|
|
- if (tmp > 0) {
|
|
- q->pmask |= 1<<prio;
|
|
- if (tmp < delay || delay == 0)
|
|
- delay = tmp;
|
|
- }
|
|
- }
|
|
-
|
|
- if (delay) {
|
|
- ktime_t time;
|
|
-
|
|
- time = 0;
|
|
- time = ktime_add_ns(time, PSCHED_TICKS2NS(now + delay));
|
|
- hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS_PINNED);
|
|
- }
|
|
-
|
|
- __netif_schedule(qdisc_root(sch));
|
|
- return HRTIMER_NORESTART;
|
|
-}
|
|
-
|
|
-/*
|
|
- * It is mission critical procedure.
|
|
- *
|
|
- * We "regenerate" toplevel cutoff, if transmitting class
|
|
- * has backlog and it is not regulated. It is not part of
|
|
- * original CBQ description, but looks more reasonable.
|
|
- * Probably, it is wrong. This question needs further investigation.
|
|
- */
|
|
-
|
|
-static inline void
|
|
-cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl,
|
|
- struct cbq_class *borrowed)
|
|
-{
|
|
- if (cl && q->toplevel >= borrowed->level) {
|
|
- if (cl->q->q.qlen > 1) {
|
|
- do {
|
|
- if (borrowed->undertime == PSCHED_PASTPERFECT) {
|
|
- q->toplevel = borrowed->level;
|
|
- return;
|
|
- }
|
|
- } while ((borrowed = borrowed->borrow) != NULL);
|
|
- }
|
|
-#if 0
|
|
- /* It is not necessary now. Uncommenting it
|
|
- will save CPU cycles, but decrease fairness.
|
|
- */
|
|
- q->toplevel = TC_CBQ_MAXLEVEL;
|
|
-#endif
|
|
- }
|
|
-}
|
|
-
|
|
-static void
|
|
-cbq_update(struct cbq_sched_data *q)
|
|
-{
|
|
- struct cbq_class *this = q->tx_class;
|
|
- struct cbq_class *cl = this;
|
|
- int len = q->tx_len;
|
|
- psched_time_t now;
|
|
-
|
|
- q->tx_class = NULL;
|
|
- /* Time integrator. We calculate EOS time
|
|
- * by adding expected packet transmission time.
|
|
- */
|
|
- now = q->now + L2T(&q->link, len);
|
|
-
|
|
- for ( ; cl; cl = cl->share) {
|
|
- long avgidle = cl->avgidle;
|
|
- long idle;
|
|
-
|
|
- cl->bstats.packets++;
|
|
- cl->bstats.bytes += len;
|
|
-
|
|
- /*
|
|
- * (now - last) is total time between packet right edges.
|
|
- * (last_pktlen/rate) is "virtual" busy time, so that
|
|
- *
|
|
- * idle = (now - last) - last_pktlen/rate
|
|
- */
|
|
-
|
|
- idle = now - cl->last;
|
|
- if ((unsigned long)idle > 128*1024*1024) {
|
|
- avgidle = cl->maxidle;
|
|
- } else {
|
|
- idle -= L2T(cl, len);
|
|
-
|
|
- /* true_avgidle := (1-W)*true_avgidle + W*idle,
|
|
- * where W=2^{-ewma_log}. But cl->avgidle is scaled:
|
|
- * cl->avgidle == true_avgidle/W,
|
|
- * hence:
|
|
- */
|
|
- avgidle += idle - (avgidle>>cl->ewma_log);
|
|
- }
|
|
-
|
|
- if (avgidle <= 0) {
|
|
- /* Overlimit or at-limit */
|
|
-
|
|
- if (avgidle < cl->minidle)
|
|
- avgidle = cl->minidle;
|
|
-
|
|
- cl->avgidle = avgidle;
|
|
-
|
|
- /* Calculate expected time, when this class
|
|
- * will be allowed to send.
|
|
- * It will occur, when:
|
|
- * (1-W)*true_avgidle + W*delay = 0, i.e.
|
|
- * idle = (1/W - 1)*(-true_avgidle)
|
|
- * or
|
|
- * idle = (1 - W)*(-cl->avgidle);
|
|
- */
|
|
- idle = (-avgidle) - ((-avgidle) >> cl->ewma_log);
|
|
-
|
|
- /*
|
|
- * That is not all.
|
|
- * To maintain the rate allocated to the class,
|
|
- * we add to undertime virtual clock,
|
|
- * necessary to complete transmitted packet.
|
|
- * (len/phys_bandwidth has been already passed
|
|
- * to the moment of cbq_update)
|
|
- */
|
|
-
|
|
- idle -= L2T(&q->link, len);
|
|
- idle += L2T(cl, len);
|
|
-
|
|
- cl->undertime = now + idle;
|
|
- } else {
|
|
- /* Underlimit */
|
|
-
|
|
- cl->undertime = PSCHED_PASTPERFECT;
|
|
- if (avgidle > cl->maxidle)
|
|
- cl->avgidle = cl->maxidle;
|
|
- else
|
|
- cl->avgidle = avgidle;
|
|
- }
|
|
- if ((s64)(now - cl->last) > 0)
|
|
- cl->last = now;
|
|
- }
|
|
-
|
|
- cbq_update_toplevel(q, this, q->tx_borrowed);
|
|
-}
|
|
-
|
|
-static inline struct cbq_class *
|
|
-cbq_under_limit(struct cbq_class *cl)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
- struct cbq_class *this_cl = cl;
|
|
-
|
|
- if (cl->tparent == NULL)
|
|
- return cl;
|
|
-
|
|
- if (cl->undertime == PSCHED_PASTPERFECT || q->now >= cl->undertime) {
|
|
- cl->delayed = 0;
|
|
- return cl;
|
|
- }
|
|
-
|
|
- do {
|
|
- /* It is very suspicious place. Now overlimit
|
|
- * action is generated for not bounded classes
|
|
- * only if link is completely congested.
|
|
- * Though it is in agree with ancestor-only paradigm,
|
|
- * it looks very stupid. Particularly,
|
|
- * it means that this chunk of code will either
|
|
- * never be called or result in strong amplification
|
|
- * of burstiness. Dangerous, silly, and, however,
|
|
- * no another solution exists.
|
|
- */
|
|
- cl = cl->borrow;
|
|
- if (!cl) {
|
|
- this_cl->qstats.overlimits++;
|
|
- cbq_overlimit(this_cl);
|
|
- return NULL;
|
|
- }
|
|
- if (cl->level > q->toplevel)
|
|
- return NULL;
|
|
- } while (cl->undertime != PSCHED_PASTPERFECT && q->now < cl->undertime);
|
|
-
|
|
- cl->delayed = 0;
|
|
- return cl;
|
|
-}
|
|
-
|
|
-static inline struct sk_buff *
|
|
-cbq_dequeue_prio(struct Qdisc *sch, int prio)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *cl_tail, *cl_prev, *cl;
|
|
- struct sk_buff *skb;
|
|
- int deficit;
|
|
-
|
|
- cl_tail = cl_prev = q->active[prio];
|
|
- cl = cl_prev->next_alive;
|
|
-
|
|
- do {
|
|
- deficit = 0;
|
|
-
|
|
- /* Start round */
|
|
- do {
|
|
- struct cbq_class *borrow = cl;
|
|
-
|
|
- if (cl->q->q.qlen &&
|
|
- (borrow = cbq_under_limit(cl)) == NULL)
|
|
- goto skip_class;
|
|
-
|
|
- if (cl->deficit <= 0) {
|
|
- /* Class exhausted its allotment per
|
|
- * this round. Switch to the next one.
|
|
- */
|
|
- deficit = 1;
|
|
- cl->deficit += cl->quantum;
|
|
- goto next_class;
|
|
- }
|
|
-
|
|
- skb = cl->q->dequeue(cl->q);
|
|
-
|
|
- /* Class did not give us any skb :-(
|
|
- * It could occur even if cl->q->q.qlen != 0
|
|
- * f.e. if cl->q == "tbf"
|
|
- */
|
|
- if (skb == NULL)
|
|
- goto skip_class;
|
|
-
|
|
- cl->deficit -= qdisc_pkt_len(skb);
|
|
- q->tx_class = cl;
|
|
- q->tx_borrowed = borrow;
|
|
- if (borrow != cl) {
|
|
-#ifndef CBQ_XSTATS_BORROWS_BYTES
|
|
- borrow->xstats.borrows++;
|
|
- cl->xstats.borrows++;
|
|
-#else
|
|
- borrow->xstats.borrows += qdisc_pkt_len(skb);
|
|
- cl->xstats.borrows += qdisc_pkt_len(skb);
|
|
-#endif
|
|
- }
|
|
- q->tx_len = qdisc_pkt_len(skb);
|
|
-
|
|
- if (cl->deficit <= 0) {
|
|
- q->active[prio] = cl;
|
|
- cl = cl->next_alive;
|
|
- cl->deficit += cl->quantum;
|
|
- }
|
|
- return skb;
|
|
-
|
|
-skip_class:
|
|
- if (cl->q->q.qlen == 0 || prio != cl->cpriority) {
|
|
- /* Class is empty or penalized.
|
|
- * Unlink it from active chain.
|
|
- */
|
|
- cl_prev->next_alive = cl->next_alive;
|
|
- cl->next_alive = NULL;
|
|
-
|
|
- /* Did cl_tail point to it? */
|
|
- if (cl == cl_tail) {
|
|
- /* Repair it! */
|
|
- cl_tail = cl_prev;
|
|
-
|
|
- /* Was it the last class in this band? */
|
|
- if (cl == cl_tail) {
|
|
- /* Kill the band! */
|
|
- q->active[prio] = NULL;
|
|
- q->activemask &= ~(1<<prio);
|
|
- if (cl->q->q.qlen)
|
|
- cbq_activate_class(cl);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- q->active[prio] = cl_tail;
|
|
- }
|
|
- if (cl->q->q.qlen)
|
|
- cbq_activate_class(cl);
|
|
-
|
|
- cl = cl_prev;
|
|
- }
|
|
-
|
|
-next_class:
|
|
- cl_prev = cl;
|
|
- cl = cl->next_alive;
|
|
- } while (cl_prev != cl_tail);
|
|
- } while (deficit);
|
|
-
|
|
- q->active[prio] = cl_prev;
|
|
-
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-static inline struct sk_buff *
|
|
-cbq_dequeue_1(struct Qdisc *sch)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct sk_buff *skb;
|
|
- unsigned int activemask;
|
|
-
|
|
- activemask = q->activemask & 0xFF;
|
|
- while (activemask) {
|
|
- int prio = ffz(~activemask);
|
|
- activemask &= ~(1<<prio);
|
|
- skb = cbq_dequeue_prio(sch, prio);
|
|
- if (skb)
|
|
- return skb;
|
|
- }
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-static struct sk_buff *
|
|
-cbq_dequeue(struct Qdisc *sch)
|
|
-{
|
|
- struct sk_buff *skb;
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- psched_time_t now;
|
|
-
|
|
- now = psched_get_time();
|
|
-
|
|
- if (q->tx_class)
|
|
- cbq_update(q);
|
|
-
|
|
- q->now = now;
|
|
-
|
|
- for (;;) {
|
|
- q->wd_expires = 0;
|
|
-
|
|
- skb = cbq_dequeue_1(sch);
|
|
- if (skb) {
|
|
- qdisc_bstats_update(sch, skb);
|
|
- sch->q.qlen--;
|
|
- return skb;
|
|
- }
|
|
-
|
|
- /* All the classes are overlimit.
|
|
- *
|
|
- * It is possible, if:
|
|
- *
|
|
- * 1. Scheduler is empty.
|
|
- * 2. Toplevel cutoff inhibited borrowing.
|
|
- * 3. Root class is overlimit.
|
|
- *
|
|
- * Reset 2d and 3d conditions and retry.
|
|
- *
|
|
- * Note, that NS and cbq-2.0 are buggy, peeking
|
|
- * an arbitrary class is appropriate for ancestor-only
|
|
- * sharing, but not for toplevel algorithm.
|
|
- *
|
|
- * Our version is better, but slower, because it requires
|
|
- * two passes, but it is unavoidable with top-level sharing.
|
|
- */
|
|
-
|
|
- if (q->toplevel == TC_CBQ_MAXLEVEL &&
|
|
- q->link.undertime == PSCHED_PASTPERFECT)
|
|
- break;
|
|
-
|
|
- q->toplevel = TC_CBQ_MAXLEVEL;
|
|
- q->link.undertime = PSCHED_PASTPERFECT;
|
|
- }
|
|
-
|
|
- /* No packets in scheduler or nobody wants to give them to us :-(
|
|
- * Sigh... start watchdog timer in the last case.
|
|
- */
|
|
-
|
|
- if (sch->q.qlen) {
|
|
- qdisc_qstats_overlimit(sch);
|
|
- if (q->wd_expires)
|
|
- qdisc_watchdog_schedule(&q->watchdog,
|
|
- now + q->wd_expires);
|
|
- }
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-/* CBQ class maintanance routines */
|
|
-
|
|
-static void cbq_adjust_levels(struct cbq_class *this)
|
|
-{
|
|
- if (this == NULL)
|
|
- return;
|
|
-
|
|
- do {
|
|
- int level = 0;
|
|
- struct cbq_class *cl;
|
|
-
|
|
- cl = this->children;
|
|
- if (cl) {
|
|
- do {
|
|
- if (cl->level > level)
|
|
- level = cl->level;
|
|
- } while ((cl = cl->sibling) != this->children);
|
|
- }
|
|
- this->level = level + 1;
|
|
- } while ((this = this->tparent) != NULL);
|
|
-}
|
|
-
|
|
-static void cbq_normalize_quanta(struct cbq_sched_data *q, int prio)
|
|
-{
|
|
- struct cbq_class *cl;
|
|
- unsigned int h;
|
|
-
|
|
- if (q->quanta[prio] == 0)
|
|
- return;
|
|
-
|
|
- for (h = 0; h < q->clhash.hashsize; h++) {
|
|
- hlist_for_each_entry(cl, &q->clhash.hash[h], common.hnode) {
|
|
- /* BUGGGG... Beware! This expression suffer of
|
|
- * arithmetic overflows!
|
|
- */
|
|
- if (cl->priority == prio) {
|
|
- cl->quantum = (cl->weight*cl->allot*q->nclasses[prio])/
|
|
- q->quanta[prio];
|
|
- }
|
|
- if (cl->quantum <= 0 ||
|
|
- cl->quantum > 32*qdisc_dev(cl->qdisc)->mtu) {
|
|
- pr_warn("CBQ: class %08x has bad quantum==%ld, repaired.\n",
|
|
- cl->common.classid, cl->quantum);
|
|
- cl->quantum = qdisc_dev(cl->qdisc)->mtu/2 + 1;
|
|
- }
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-static void cbq_sync_defmap(struct cbq_class *cl)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
- struct cbq_class *split = cl->split;
|
|
- unsigned int h;
|
|
- int i;
|
|
-
|
|
- if (split == NULL)
|
|
- return;
|
|
-
|
|
- for (i = 0; i <= TC_PRIO_MAX; i++) {
|
|
- if (split->defaults[i] == cl && !(cl->defmap & (1<<i)))
|
|
- split->defaults[i] = NULL;
|
|
- }
|
|
-
|
|
- for (i = 0; i <= TC_PRIO_MAX; i++) {
|
|
- int level = split->level;
|
|
-
|
|
- if (split->defaults[i])
|
|
- continue;
|
|
-
|
|
- for (h = 0; h < q->clhash.hashsize; h++) {
|
|
- struct cbq_class *c;
|
|
-
|
|
- hlist_for_each_entry(c, &q->clhash.hash[h],
|
|
- common.hnode) {
|
|
- if (c->split == split && c->level < level &&
|
|
- c->defmap & (1<<i)) {
|
|
- split->defaults[i] = c;
|
|
- level = c->level;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-static void cbq_change_defmap(struct cbq_class *cl, u32 splitid, u32 def, u32 mask)
|
|
-{
|
|
- struct cbq_class *split = NULL;
|
|
-
|
|
- if (splitid == 0) {
|
|
- split = cl->split;
|
|
- if (!split)
|
|
- return;
|
|
- splitid = split->common.classid;
|
|
- }
|
|
-
|
|
- if (split == NULL || split->common.classid != splitid) {
|
|
- for (split = cl->tparent; split; split = split->tparent)
|
|
- if (split->common.classid == splitid)
|
|
- break;
|
|
- }
|
|
-
|
|
- if (split == NULL)
|
|
- return;
|
|
-
|
|
- if (cl->split != split) {
|
|
- cl->defmap = 0;
|
|
- cbq_sync_defmap(cl);
|
|
- cl->split = split;
|
|
- cl->defmap = def & mask;
|
|
- } else
|
|
- cl->defmap = (cl->defmap & ~mask) | (def & mask);
|
|
-
|
|
- cbq_sync_defmap(cl);
|
|
-}
|
|
-
|
|
-static void cbq_unlink_class(struct cbq_class *this)
|
|
-{
|
|
- struct cbq_class *cl, **clp;
|
|
- struct cbq_sched_data *q = qdisc_priv(this->qdisc);
|
|
-
|
|
- qdisc_class_hash_remove(&q->clhash, &this->common);
|
|
-
|
|
- if (this->tparent) {
|
|
- clp = &this->sibling;
|
|
- cl = *clp;
|
|
- do {
|
|
- if (cl == this) {
|
|
- *clp = cl->sibling;
|
|
- break;
|
|
- }
|
|
- clp = &cl->sibling;
|
|
- } while ((cl = *clp) != this->sibling);
|
|
-
|
|
- if (this->tparent->children == this) {
|
|
- this->tparent->children = this->sibling;
|
|
- if (this->sibling == this)
|
|
- this->tparent->children = NULL;
|
|
- }
|
|
- } else {
|
|
- WARN_ON(this->sibling != this);
|
|
- }
|
|
-}
|
|
-
|
|
-static void cbq_link_class(struct cbq_class *this)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(this->qdisc);
|
|
- struct cbq_class *parent = this->tparent;
|
|
-
|
|
- this->sibling = this;
|
|
- qdisc_class_hash_insert(&q->clhash, &this->common);
|
|
-
|
|
- if (parent == NULL)
|
|
- return;
|
|
-
|
|
- if (parent->children == NULL) {
|
|
- parent->children = this;
|
|
- } else {
|
|
- this->sibling = parent->children->sibling;
|
|
- parent->children->sibling = this;
|
|
- }
|
|
-}
|
|
-
|
|
-static void
|
|
-cbq_reset(struct Qdisc *sch)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *cl;
|
|
- int prio;
|
|
- unsigned int h;
|
|
-
|
|
- q->activemask = 0;
|
|
- q->pmask = 0;
|
|
- q->tx_class = NULL;
|
|
- q->tx_borrowed = NULL;
|
|
- qdisc_watchdog_cancel(&q->watchdog);
|
|
- hrtimer_cancel(&q->delay_timer);
|
|
- q->toplevel = TC_CBQ_MAXLEVEL;
|
|
- q->now = psched_get_time();
|
|
-
|
|
- for (prio = 0; prio <= TC_CBQ_MAXPRIO; prio++)
|
|
- q->active[prio] = NULL;
|
|
-
|
|
- for (h = 0; h < q->clhash.hashsize; h++) {
|
|
- hlist_for_each_entry(cl, &q->clhash.hash[h], common.hnode) {
|
|
- qdisc_reset(cl->q);
|
|
-
|
|
- cl->next_alive = NULL;
|
|
- cl->undertime = PSCHED_PASTPERFECT;
|
|
- cl->avgidle = cl->maxidle;
|
|
- cl->deficit = cl->quantum;
|
|
- cl->cpriority = cl->priority;
|
|
- }
|
|
- }
|
|
- sch->q.qlen = 0;
|
|
-}
|
|
-
|
|
-
|
|
-static int cbq_set_lss(struct cbq_class *cl, struct tc_cbq_lssopt *lss)
|
|
-{
|
|
- if (lss->change & TCF_CBQ_LSS_FLAGS) {
|
|
- cl->share = (lss->flags & TCF_CBQ_LSS_ISOLATED) ? NULL : cl->tparent;
|
|
- cl->borrow = (lss->flags & TCF_CBQ_LSS_BOUNDED) ? NULL : cl->tparent;
|
|
- }
|
|
- if (lss->change & TCF_CBQ_LSS_EWMA)
|
|
- cl->ewma_log = lss->ewma_log;
|
|
- if (lss->change & TCF_CBQ_LSS_AVPKT)
|
|
- cl->avpkt = lss->avpkt;
|
|
- if (lss->change & TCF_CBQ_LSS_MINIDLE)
|
|
- cl->minidle = -(long)lss->minidle;
|
|
- if (lss->change & TCF_CBQ_LSS_MAXIDLE) {
|
|
- cl->maxidle = lss->maxidle;
|
|
- cl->avgidle = lss->maxidle;
|
|
- }
|
|
- if (lss->change & TCF_CBQ_LSS_OFFTIME)
|
|
- cl->offtime = lss->offtime;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void cbq_rmprio(struct cbq_sched_data *q, struct cbq_class *cl)
|
|
-{
|
|
- q->nclasses[cl->priority]--;
|
|
- q->quanta[cl->priority] -= cl->weight;
|
|
- cbq_normalize_quanta(q, cl->priority);
|
|
-}
|
|
-
|
|
-static void cbq_addprio(struct cbq_sched_data *q, struct cbq_class *cl)
|
|
-{
|
|
- q->nclasses[cl->priority]++;
|
|
- q->quanta[cl->priority] += cl->weight;
|
|
- cbq_normalize_quanta(q, cl->priority);
|
|
-}
|
|
-
|
|
-static int cbq_set_wrr(struct cbq_class *cl, struct tc_cbq_wrropt *wrr)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
-
|
|
- if (wrr->allot)
|
|
- cl->allot = wrr->allot;
|
|
- if (wrr->weight)
|
|
- cl->weight = wrr->weight;
|
|
- if (wrr->priority) {
|
|
- cl->priority = wrr->priority - 1;
|
|
- cl->cpriority = cl->priority;
|
|
- if (cl->priority >= cl->priority2)
|
|
- cl->priority2 = TC_CBQ_MAXPRIO - 1;
|
|
- }
|
|
-
|
|
- cbq_addprio(q, cl);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
|
|
-{
|
|
- cbq_change_defmap(cl, fopt->split, fopt->defmap, fopt->defchange);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
|
|
- [TCA_CBQ_LSSOPT] = { .len = sizeof(struct tc_cbq_lssopt) },
|
|
- [TCA_CBQ_WRROPT] = { .len = sizeof(struct tc_cbq_wrropt) },
|
|
- [TCA_CBQ_FOPT] = { .len = sizeof(struct tc_cbq_fopt) },
|
|
- [TCA_CBQ_OVL_STRATEGY] = { .len = sizeof(struct tc_cbq_ovl) },
|
|
- [TCA_CBQ_RATE] = { .len = sizeof(struct tc_ratespec) },
|
|
- [TCA_CBQ_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
|
|
- [TCA_CBQ_POLICE] = { .len = sizeof(struct tc_cbq_police) },
|
|
-};
|
|
-
|
|
-static int cbq_opt_parse(struct nlattr *tb[TCA_CBQ_MAX + 1], struct nlattr *opt)
|
|
-{
|
|
- int err;
|
|
-
|
|
- if (!opt)
|
|
- return -EINVAL;
|
|
-
|
|
- err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, NULL);
|
|
- if (err < 0)
|
|
- return err;
|
|
-
|
|
- if (tb[TCA_CBQ_WRROPT]) {
|
|
- const struct tc_cbq_wrropt *wrr = nla_data(tb[TCA_CBQ_WRROPT]);
|
|
-
|
|
- if (wrr->priority > TC_CBQ_MAXPRIO)
|
|
- err = -EINVAL;
|
|
- }
|
|
- return err;
|
|
-}
|
|
-
|
|
-static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct nlattr *tb[TCA_CBQ_MAX + 1];
|
|
- struct tc_ratespec *r;
|
|
- int err;
|
|
-
|
|
- qdisc_watchdog_init(&q->watchdog, sch);
|
|
- hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
|
|
- q->delay_timer.function = cbq_undelay;
|
|
-
|
|
- err = cbq_opt_parse(tb, opt);
|
|
- if (err < 0)
|
|
- return err;
|
|
-
|
|
- if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- r = nla_data(tb[TCA_CBQ_RATE]);
|
|
-
|
|
- if ((q->link.R_tab = qdisc_get_rtab(r, tb[TCA_CBQ_RTAB])) == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- err = tcf_block_get(&q->link.block, &q->link.filter_list);
|
|
- if (err)
|
|
- goto put_rtab;
|
|
-
|
|
- err = qdisc_class_hash_init(&q->clhash);
|
|
- if (err < 0)
|
|
- goto put_block;
|
|
-
|
|
- q->link.sibling = &q->link;
|
|
- q->link.common.classid = sch->handle;
|
|
- q->link.qdisc = sch;
|
|
- q->link.q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
|
|
- sch->handle);
|
|
- if (!q->link.q)
|
|
- q->link.q = &noop_qdisc;
|
|
- else
|
|
- qdisc_hash_add(q->link.q, true);
|
|
-
|
|
- q->link.priority = TC_CBQ_MAXPRIO - 1;
|
|
- q->link.priority2 = TC_CBQ_MAXPRIO - 1;
|
|
- q->link.cpriority = TC_CBQ_MAXPRIO - 1;
|
|
- q->link.allot = psched_mtu(qdisc_dev(sch));
|
|
- q->link.quantum = q->link.allot;
|
|
- q->link.weight = q->link.R_tab->rate.rate;
|
|
-
|
|
- q->link.ewma_log = TC_CBQ_DEF_EWMA;
|
|
- q->link.avpkt = q->link.allot/2;
|
|
- q->link.minidle = -0x7FFFFFFF;
|
|
-
|
|
- q->toplevel = TC_CBQ_MAXLEVEL;
|
|
- q->now = psched_get_time();
|
|
-
|
|
- cbq_link_class(&q->link);
|
|
-
|
|
- if (tb[TCA_CBQ_LSSOPT])
|
|
- cbq_set_lss(&q->link, nla_data(tb[TCA_CBQ_LSSOPT]));
|
|
-
|
|
- cbq_addprio(q, &q->link);
|
|
- return 0;
|
|
-
|
|
-put_block:
|
|
- tcf_block_put(q->link.block);
|
|
-
|
|
-put_rtab:
|
|
- qdisc_put_rtab(q->link.R_tab);
|
|
- return err;
|
|
-}
|
|
-
|
|
-static int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl)
|
|
-{
|
|
- unsigned char *b = skb_tail_pointer(skb);
|
|
-
|
|
- if (nla_put(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate))
|
|
- goto nla_put_failure;
|
|
- return skb->len;
|
|
-
|
|
-nla_put_failure:
|
|
- nlmsg_trim(skb, b);
|
|
- return -1;
|
|
-}
|
|
-
|
|
-static int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl)
|
|
-{
|
|
- unsigned char *b = skb_tail_pointer(skb);
|
|
- struct tc_cbq_lssopt opt;
|
|
-
|
|
- opt.flags = 0;
|
|
- if (cl->borrow == NULL)
|
|
- opt.flags |= TCF_CBQ_LSS_BOUNDED;
|
|
- if (cl->share == NULL)
|
|
- opt.flags |= TCF_CBQ_LSS_ISOLATED;
|
|
- opt.ewma_log = cl->ewma_log;
|
|
- opt.level = cl->level;
|
|
- opt.avpkt = cl->avpkt;
|
|
- opt.maxidle = cl->maxidle;
|
|
- opt.minidle = (u32)(-cl->minidle);
|
|
- opt.offtime = cl->offtime;
|
|
- opt.change = ~0;
|
|
- if (nla_put(skb, TCA_CBQ_LSSOPT, sizeof(opt), &opt))
|
|
- goto nla_put_failure;
|
|
- return skb->len;
|
|
-
|
|
-nla_put_failure:
|
|
- nlmsg_trim(skb, b);
|
|
- return -1;
|
|
-}
|
|
-
|
|
-static int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl)
|
|
-{
|
|
- unsigned char *b = skb_tail_pointer(skb);
|
|
- struct tc_cbq_wrropt opt;
|
|
-
|
|
- memset(&opt, 0, sizeof(opt));
|
|
- opt.flags = 0;
|
|
- opt.allot = cl->allot;
|
|
- opt.priority = cl->priority + 1;
|
|
- opt.cpriority = cl->cpriority + 1;
|
|
- opt.weight = cl->weight;
|
|
- if (nla_put(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt))
|
|
- goto nla_put_failure;
|
|
- return skb->len;
|
|
-
|
|
-nla_put_failure:
|
|
- nlmsg_trim(skb, b);
|
|
- return -1;
|
|
-}
|
|
-
|
|
-static int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl)
|
|
-{
|
|
- unsigned char *b = skb_tail_pointer(skb);
|
|
- struct tc_cbq_fopt opt;
|
|
-
|
|
- if (cl->split || cl->defmap) {
|
|
- opt.split = cl->split ? cl->split->common.classid : 0;
|
|
- opt.defmap = cl->defmap;
|
|
- opt.defchange = ~0;
|
|
- if (nla_put(skb, TCA_CBQ_FOPT, sizeof(opt), &opt))
|
|
- goto nla_put_failure;
|
|
- }
|
|
- return skb->len;
|
|
-
|
|
-nla_put_failure:
|
|
- nlmsg_trim(skb, b);
|
|
- return -1;
|
|
-}
|
|
-
|
|
-static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl)
|
|
-{
|
|
- if (cbq_dump_lss(skb, cl) < 0 ||
|
|
- cbq_dump_rate(skb, cl) < 0 ||
|
|
- cbq_dump_wrr(skb, cl) < 0 ||
|
|
- cbq_dump_fopt(skb, cl) < 0)
|
|
- return -1;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct nlattr *nest;
|
|
-
|
|
- nest = nla_nest_start(skb, TCA_OPTIONS);
|
|
- if (nest == NULL)
|
|
- goto nla_put_failure;
|
|
- if (cbq_dump_attr(skb, &q->link) < 0)
|
|
- goto nla_put_failure;
|
|
- return nla_nest_end(skb, nest);
|
|
-
|
|
-nla_put_failure:
|
|
- nla_nest_cancel(skb, nest);
|
|
- return -1;
|
|
-}
|
|
-
|
|
-static int
|
|
-cbq_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
-
|
|
- q->link.xstats.avgidle = q->link.avgidle;
|
|
- return gnet_stats_copy_app(d, &q->link.xstats, sizeof(q->link.xstats));
|
|
-}
|
|
-
|
|
-static int
|
|
-cbq_dump_class(struct Qdisc *sch, unsigned long arg,
|
|
- struct sk_buff *skb, struct tcmsg *tcm)
|
|
-{
|
|
- struct cbq_class *cl = (struct cbq_class *)arg;
|
|
- struct nlattr *nest;
|
|
-
|
|
- if (cl->tparent)
|
|
- tcm->tcm_parent = cl->tparent->common.classid;
|
|
- else
|
|
- tcm->tcm_parent = TC_H_ROOT;
|
|
- tcm->tcm_handle = cl->common.classid;
|
|
- tcm->tcm_info = cl->q->handle;
|
|
-
|
|
- nest = nla_nest_start(skb, TCA_OPTIONS);
|
|
- if (nest == NULL)
|
|
- goto nla_put_failure;
|
|
- if (cbq_dump_attr(skb, cl) < 0)
|
|
- goto nla_put_failure;
|
|
- return nla_nest_end(skb, nest);
|
|
-
|
|
-nla_put_failure:
|
|
- nla_nest_cancel(skb, nest);
|
|
- return -1;
|
|
-}
|
|
-
|
|
-static int
|
|
-cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
|
|
- struct gnet_dump *d)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *cl = (struct cbq_class *)arg;
|
|
-
|
|
- cl->xstats.avgidle = cl->avgidle;
|
|
- cl->xstats.undertime = 0;
|
|
-
|
|
- if (cl->undertime != PSCHED_PASTPERFECT)
|
|
- cl->xstats.undertime = cl->undertime - q->now;
|
|
-
|
|
- if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
|
|
- d, NULL, &cl->bstats) < 0 ||
|
|
- gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
|
|
- gnet_stats_copy_queue(d, NULL, &cl->qstats, cl->q->q.qlen) < 0)
|
|
- return -1;
|
|
-
|
|
- return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
|
|
-}
|
|
-
|
|
-static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
|
|
- struct Qdisc **old)
|
|
-{
|
|
- struct cbq_class *cl = (struct cbq_class *)arg;
|
|
-
|
|
- if (new == NULL) {
|
|
- new = qdisc_create_dflt(sch->dev_queue,
|
|
- &pfifo_qdisc_ops, cl->common.classid);
|
|
- if (new == NULL)
|
|
- return -ENOBUFS;
|
|
- }
|
|
-
|
|
- *old = qdisc_replace(sch, new, &cl->q);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static struct Qdisc *cbq_leaf(struct Qdisc *sch, unsigned long arg)
|
|
-{
|
|
- struct cbq_class *cl = (struct cbq_class *)arg;
|
|
-
|
|
- return cl->q;
|
|
-}
|
|
-
|
|
-static void cbq_qlen_notify(struct Qdisc *sch, unsigned long arg)
|
|
-{
|
|
- struct cbq_class *cl = (struct cbq_class *)arg;
|
|
-
|
|
- cbq_deactivate_class(cl);
|
|
-}
|
|
-
|
|
-static unsigned long cbq_find(struct Qdisc *sch, u32 classid)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
-
|
|
- return (unsigned long)cbq_class_lookup(q, classid);
|
|
-}
|
|
-
|
|
-static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
-
|
|
- WARN_ON(cl->filters);
|
|
-
|
|
- tcf_block_put(cl->block);
|
|
- qdisc_destroy(cl->q);
|
|
- qdisc_put_rtab(cl->R_tab);
|
|
- gen_kill_estimator(&cl->rate_est);
|
|
- if (cl != &q->link)
|
|
- kfree(cl);
|
|
-}
|
|
-
|
|
-static void cbq_destroy(struct Qdisc *sch)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct hlist_node *next;
|
|
- struct cbq_class *cl;
|
|
- unsigned int h;
|
|
-
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
- q->rx_class = NULL;
|
|
-#endif
|
|
- /*
|
|
- * Filters must be destroyed first because we don't destroy the
|
|
- * classes from root to leafs which means that filters can still
|
|
- * be bound to classes which have been destroyed already. --TGR '04
|
|
- */
|
|
- for (h = 0; h < q->clhash.hashsize; h++) {
|
|
- hlist_for_each_entry(cl, &q->clhash.hash[h], common.hnode) {
|
|
- tcf_block_put(cl->block);
|
|
- cl->block = NULL;
|
|
- }
|
|
- }
|
|
- for (h = 0; h < q->clhash.hashsize; h++) {
|
|
- hlist_for_each_entry_safe(cl, next, &q->clhash.hash[h],
|
|
- common.hnode)
|
|
- cbq_destroy_class(sch, cl);
|
|
- }
|
|
- qdisc_class_hash_destroy(&q->clhash);
|
|
-}
|
|
-
|
|
-static int
|
|
-cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **tca,
|
|
- unsigned long *arg)
|
|
-{
|
|
- int err;
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *cl = (struct cbq_class *)*arg;
|
|
- struct nlattr *opt = tca[TCA_OPTIONS];
|
|
- struct nlattr *tb[TCA_CBQ_MAX + 1];
|
|
- struct cbq_class *parent;
|
|
- struct qdisc_rate_table *rtab = NULL;
|
|
-
|
|
- err = cbq_opt_parse(tb, opt);
|
|
- if (err < 0)
|
|
- return err;
|
|
-
|
|
- if (tb[TCA_CBQ_OVL_STRATEGY] || tb[TCA_CBQ_POLICE])
|
|
- return -EOPNOTSUPP;
|
|
-
|
|
- if (cl) {
|
|
- /* Check parent */
|
|
- if (parentid) {
|
|
- if (cl->tparent &&
|
|
- cl->tparent->common.classid != parentid)
|
|
- return -EINVAL;
|
|
- if (!cl->tparent && parentid != TC_H_ROOT)
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if (tb[TCA_CBQ_RATE]) {
|
|
- rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]),
|
|
- tb[TCA_CBQ_RTAB]);
|
|
- if (rtab == NULL)
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if (tca[TCA_RATE]) {
|
|
- err = gen_replace_estimator(&cl->bstats, NULL,
|
|
- &cl->rate_est,
|
|
- NULL,
|
|
- qdisc_root_sleeping_running(sch),
|
|
- tca[TCA_RATE]);
|
|
- if (err) {
|
|
- qdisc_put_rtab(rtab);
|
|
- return err;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Change class parameters */
|
|
- sch_tree_lock(sch);
|
|
-
|
|
- if (cl->next_alive != NULL)
|
|
- cbq_deactivate_class(cl);
|
|
-
|
|
- if (rtab) {
|
|
- qdisc_put_rtab(cl->R_tab);
|
|
- cl->R_tab = rtab;
|
|
- }
|
|
-
|
|
- if (tb[TCA_CBQ_LSSOPT])
|
|
- cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
|
|
-
|
|
- if (tb[TCA_CBQ_WRROPT]) {
|
|
- cbq_rmprio(q, cl);
|
|
- cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
|
|
- }
|
|
-
|
|
- if (tb[TCA_CBQ_FOPT])
|
|
- cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
|
|
-
|
|
- if (cl->q->q.qlen)
|
|
- cbq_activate_class(cl);
|
|
-
|
|
- sch_tree_unlock(sch);
|
|
-
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (parentid == TC_H_ROOT)
|
|
- return -EINVAL;
|
|
-
|
|
- if (tb[TCA_CBQ_WRROPT] == NULL || tb[TCA_CBQ_RATE] == NULL ||
|
|
- tb[TCA_CBQ_LSSOPT] == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]);
|
|
- if (rtab == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- if (classid) {
|
|
- err = -EINVAL;
|
|
- if (TC_H_MAJ(classid ^ sch->handle) ||
|
|
- cbq_class_lookup(q, classid))
|
|
- goto failure;
|
|
- } else {
|
|
- int i;
|
|
- classid = TC_H_MAKE(sch->handle, 0x8000);
|
|
-
|
|
- for (i = 0; i < 0x8000; i++) {
|
|
- if (++q->hgenerator >= 0x8000)
|
|
- q->hgenerator = 1;
|
|
- if (cbq_class_lookup(q, classid|q->hgenerator) == NULL)
|
|
- break;
|
|
- }
|
|
- err = -ENOSR;
|
|
- if (i >= 0x8000)
|
|
- goto failure;
|
|
- classid = classid|q->hgenerator;
|
|
- }
|
|
-
|
|
- parent = &q->link;
|
|
- if (parentid) {
|
|
- parent = cbq_class_lookup(q, parentid);
|
|
- err = -EINVAL;
|
|
- if (parent == NULL)
|
|
- goto failure;
|
|
- }
|
|
-
|
|
- err = -ENOBUFS;
|
|
- cl = kzalloc(sizeof(*cl), GFP_KERNEL);
|
|
- if (cl == NULL)
|
|
- goto failure;
|
|
-
|
|
- err = tcf_block_get(&cl->block, &cl->filter_list);
|
|
- if (err) {
|
|
- kfree(cl);
|
|
- goto failure;
|
|
- }
|
|
-
|
|
- if (tca[TCA_RATE]) {
|
|
- err = gen_new_estimator(&cl->bstats, NULL, &cl->rate_est,
|
|
- NULL,
|
|
- qdisc_root_sleeping_running(sch),
|
|
- tca[TCA_RATE]);
|
|
- if (err) {
|
|
- tcf_block_put(cl->block);
|
|
- kfree(cl);
|
|
- goto failure;
|
|
- }
|
|
- }
|
|
-
|
|
- cl->R_tab = rtab;
|
|
- rtab = NULL;
|
|
- cl->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
|
|
- if (!cl->q)
|
|
- cl->q = &noop_qdisc;
|
|
- else
|
|
- qdisc_hash_add(cl->q, true);
|
|
-
|
|
- cl->common.classid = classid;
|
|
- cl->tparent = parent;
|
|
- cl->qdisc = sch;
|
|
- cl->allot = parent->allot;
|
|
- cl->quantum = cl->allot;
|
|
- cl->weight = cl->R_tab->rate.rate;
|
|
-
|
|
- sch_tree_lock(sch);
|
|
- cbq_link_class(cl);
|
|
- cl->borrow = cl->tparent;
|
|
- if (cl->tparent != &q->link)
|
|
- cl->share = cl->tparent;
|
|
- cbq_adjust_levels(parent);
|
|
- cl->minidle = -0x7FFFFFFF;
|
|
- cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
|
|
- cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
|
|
- if (cl->ewma_log == 0)
|
|
- cl->ewma_log = q->link.ewma_log;
|
|
- if (cl->maxidle == 0)
|
|
- cl->maxidle = q->link.maxidle;
|
|
- if (cl->avpkt == 0)
|
|
- cl->avpkt = q->link.avpkt;
|
|
- if (tb[TCA_CBQ_FOPT])
|
|
- cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
|
|
- sch_tree_unlock(sch);
|
|
-
|
|
- qdisc_class_hash_grow(sch, &q->clhash);
|
|
-
|
|
- *arg = (unsigned long)cl;
|
|
- return 0;
|
|
-
|
|
-failure:
|
|
- qdisc_put_rtab(rtab);
|
|
- return err;
|
|
-}
|
|
-
|
|
-static int cbq_delete(struct Qdisc *sch, unsigned long arg)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *cl = (struct cbq_class *)arg;
|
|
- unsigned int qlen, backlog;
|
|
-
|
|
- if (cl->filters || cl->children || cl == &q->link)
|
|
- return -EBUSY;
|
|
-
|
|
- sch_tree_lock(sch);
|
|
-
|
|
- qlen = cl->q->q.qlen;
|
|
- backlog = cl->q->qstats.backlog;
|
|
- qdisc_reset(cl->q);
|
|
- qdisc_tree_reduce_backlog(cl->q, qlen, backlog);
|
|
-
|
|
- if (cl->next_alive)
|
|
- cbq_deactivate_class(cl);
|
|
-
|
|
- if (q->tx_borrowed == cl)
|
|
- q->tx_borrowed = q->tx_class;
|
|
- if (q->tx_class == cl) {
|
|
- q->tx_class = NULL;
|
|
- q->tx_borrowed = NULL;
|
|
- }
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
- if (q->rx_class == cl)
|
|
- q->rx_class = NULL;
|
|
-#endif
|
|
-
|
|
- cbq_unlink_class(cl);
|
|
- cbq_adjust_levels(cl->tparent);
|
|
- cl->defmap = 0;
|
|
- cbq_sync_defmap(cl);
|
|
-
|
|
- cbq_rmprio(q, cl);
|
|
- sch_tree_unlock(sch);
|
|
-
|
|
- cbq_destroy_class(sch, cl);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static struct tcf_block *cbq_tcf_block(struct Qdisc *sch, unsigned long arg)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *cl = (struct cbq_class *)arg;
|
|
-
|
|
- if (cl == NULL)
|
|
- cl = &q->link;
|
|
-
|
|
- return cl->block;
|
|
-}
|
|
-
|
|
-static unsigned long cbq_bind_filter(struct Qdisc *sch, unsigned long parent,
|
|
- u32 classid)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *p = (struct cbq_class *)parent;
|
|
- struct cbq_class *cl = cbq_class_lookup(q, classid);
|
|
-
|
|
- if (cl) {
|
|
- if (p && p->level <= cl->level)
|
|
- return 0;
|
|
- cl->filters++;
|
|
- return (unsigned long)cl;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void cbq_unbind_filter(struct Qdisc *sch, unsigned long arg)
|
|
-{
|
|
- struct cbq_class *cl = (struct cbq_class *)arg;
|
|
-
|
|
- cl->filters--;
|
|
-}
|
|
-
|
|
-static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
|
|
-{
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
- struct cbq_class *cl;
|
|
- unsigned int h;
|
|
-
|
|
- if (arg->stop)
|
|
- return;
|
|
-
|
|
- for (h = 0; h < q->clhash.hashsize; h++) {
|
|
- hlist_for_each_entry(cl, &q->clhash.hash[h], common.hnode) {
|
|
- if (arg->count < arg->skip) {
|
|
- arg->count++;
|
|
- continue;
|
|
- }
|
|
- if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
|
|
- arg->stop = 1;
|
|
- return;
|
|
- }
|
|
- arg->count++;
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-static const struct Qdisc_class_ops cbq_class_ops = {
|
|
- .graft = cbq_graft,
|
|
- .leaf = cbq_leaf,
|
|
- .qlen_notify = cbq_qlen_notify,
|
|
- .find = cbq_find,
|
|
- .change = cbq_change_class,
|
|
- .delete = cbq_delete,
|
|
- .walk = cbq_walk,
|
|
- .tcf_block = cbq_tcf_block,
|
|
- .bind_tcf = cbq_bind_filter,
|
|
- .unbind_tcf = cbq_unbind_filter,
|
|
- .dump = cbq_dump_class,
|
|
- .dump_stats = cbq_dump_class_stats,
|
|
-};
|
|
-
|
|
-static struct Qdisc_ops cbq_qdisc_ops __read_mostly = {
|
|
- .next = NULL,
|
|
- .cl_ops = &cbq_class_ops,
|
|
- .id = "cbq",
|
|
- .priv_size = sizeof(struct cbq_sched_data),
|
|
- .enqueue = cbq_enqueue,
|
|
- .dequeue = cbq_dequeue,
|
|
- .peek = qdisc_peek_dequeued,
|
|
- .init = cbq_init,
|
|
- .reset = cbq_reset,
|
|
- .destroy = cbq_destroy,
|
|
- .change = NULL,
|
|
- .dump = cbq_dump,
|
|
- .dump_stats = cbq_dump_stats,
|
|
- .owner = THIS_MODULE,
|
|
-};
|
|
-
|
|
-static int __init cbq_module_init(void)
|
|
-{
|
|
- return register_qdisc(&cbq_qdisc_ops);
|
|
-}
|
|
-static void __exit cbq_module_exit(void)
|
|
-{
|
|
- unregister_qdisc(&cbq_qdisc_ops);
|
|
-}
|
|
-module_init(cbq_module_init)
|
|
-module_exit(cbq_module_exit)
|
|
-MODULE_LICENSE("GPL");
|
|
diff --git net/sched/sch_dsmark.c net/sched/sch_dsmark.c
|
|
deleted file mode 100644
|
|
index b972d50828ca..000000000000
|
|
--- net/sched/sch_dsmark.c
|
|
+++ /dev/null
|
|
@@ -1,514 +0,0 @@
|
|
-/* net/sched/sch_dsmark.c - Differentiated Services field marker */
|
|
-
|
|
-/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
|
|
-
|
|
-
|
|
-#include <linux/module.h>
|
|
-#include <linux/init.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/types.h>
|
|
-#include <linux/string.h>
|
|
-#include <linux/errno.h>
|
|
-#include <linux/skbuff.h>
|
|
-#include <linux/rtnetlink.h>
|
|
-#include <linux/bitops.h>
|
|
-#include <net/pkt_sched.h>
|
|
-#include <net/pkt_cls.h>
|
|
-#include <net/dsfield.h>
|
|
-#include <net/inet_ecn.h>
|
|
-#include <asm/byteorder.h>
|
|
-
|
|
-/*
|
|
- * classid class marking
|
|
- * ------- ----- -------
|
|
- * n/a 0 n/a
|
|
- * x:0 1 use entry [0]
|
|
- * ... ... ...
|
|
- * x:y y>0 y+1 use entry [y]
|
|
- * ... ... ...
|
|
- * x:indices-1 indices use entry [indices-1]
|
|
- * ... ... ...
|
|
- * x:y y+1 use entry [y & (indices-1)]
|
|
- * ... ... ...
|
|
- * 0xffff 0x10000 use entry [indices-1]
|
|
- */
|
|
-
|
|
-
|
|
-#define NO_DEFAULT_INDEX (1 << 16)
|
|
-
|
|
-struct mask_value {
|
|
- u8 mask;
|
|
- u8 value;
|
|
-};
|
|
-
|
|
-struct dsmark_qdisc_data {
|
|
- struct Qdisc *q;
|
|
- struct tcf_proto __rcu *filter_list;
|
|
- struct tcf_block *block;
|
|
- struct mask_value *mv;
|
|
- u16 indices;
|
|
- u8 set_tc_index;
|
|
- u32 default_index; /* index range is 0...0xffff */
|
|
-#define DSMARK_EMBEDDED_SZ 16
|
|
- struct mask_value embedded[DSMARK_EMBEDDED_SZ];
|
|
-};
|
|
-
|
|
-static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
|
|
-{
|
|
- return index <= p->indices && index > 0;
|
|
-}
|
|
-
|
|
-/* ------------------------- Class/flow operations ------------------------- */
|
|
-
|
|
-static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
|
|
- struct Qdisc *new, struct Qdisc **old)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p],new %p,old %p)\n",
|
|
- __func__, sch, p, new, old);
|
|
-
|
|
- if (new == NULL) {
|
|
- new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
|
|
- sch->handle);
|
|
- if (new == NULL)
|
|
- new = &noop_qdisc;
|
|
- }
|
|
-
|
|
- *old = qdisc_replace(sch, new, &p->q);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
- return p->q;
|
|
-}
|
|
-
|
|
-static unsigned long dsmark_find(struct Qdisc *sch, u32 classid)
|
|
-{
|
|
- return TC_H_MIN(classid) + 1;
|
|
-}
|
|
-
|
|
-static unsigned long dsmark_bind_filter(struct Qdisc *sch,
|
|
- unsigned long parent, u32 classid)
|
|
-{
|
|
- pr_debug("%s(sch %p,[qdisc %p],classid %x)\n",
|
|
- __func__, sch, qdisc_priv(sch), classid);
|
|
-
|
|
- return dsmark_find(sch, classid);
|
|
-}
|
|
-
|
|
-static void dsmark_unbind_filter(struct Qdisc *sch, unsigned long cl)
|
|
-{
|
|
-}
|
|
-
|
|
-static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = {
|
|
- [TCA_DSMARK_INDICES] = { .type = NLA_U16 },
|
|
- [TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 },
|
|
- [TCA_DSMARK_SET_TC_INDEX] = { .type = NLA_FLAG },
|
|
- [TCA_DSMARK_MASK] = { .type = NLA_U8 },
|
|
- [TCA_DSMARK_VALUE] = { .type = NLA_U8 },
|
|
-};
|
|
-
|
|
-static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
|
|
- struct nlattr **tca, unsigned long *arg)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
- struct nlattr *opt = tca[TCA_OPTIONS];
|
|
- struct nlattr *tb[TCA_DSMARK_MAX + 1];
|
|
- int err = -EINVAL;
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p],classid %x,parent %x), arg 0x%lx\n",
|
|
- __func__, sch, p, classid, parent, *arg);
|
|
-
|
|
- if (!dsmark_valid_index(p, *arg)) {
|
|
- err = -ENOENT;
|
|
- goto errout;
|
|
- }
|
|
-
|
|
- if (!opt)
|
|
- goto errout;
|
|
-
|
|
- err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy, NULL);
|
|
- if (err < 0)
|
|
- goto errout;
|
|
-
|
|
- if (tb[TCA_DSMARK_VALUE])
|
|
- p->mv[*arg - 1].value = nla_get_u8(tb[TCA_DSMARK_VALUE]);
|
|
-
|
|
- if (tb[TCA_DSMARK_MASK])
|
|
- p->mv[*arg - 1].mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
|
|
-
|
|
- err = 0;
|
|
-
|
|
-errout:
|
|
- return err;
|
|
-}
|
|
-
|
|
-static int dsmark_delete(struct Qdisc *sch, unsigned long arg)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
-
|
|
- if (!dsmark_valid_index(p, arg))
|
|
- return -EINVAL;
|
|
-
|
|
- p->mv[arg - 1].mask = 0xff;
|
|
- p->mv[arg - 1].value = 0;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
- int i;
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p],walker %p)\n",
|
|
- __func__, sch, p, walker);
|
|
-
|
|
- if (walker->stop)
|
|
- return;
|
|
-
|
|
- for (i = 0; i < p->indices; i++) {
|
|
- if (p->mv[i].mask == 0xff && !p->mv[i].value)
|
|
- goto ignore;
|
|
- if (walker->count >= walker->skip) {
|
|
- if (walker->fn(sch, i + 1, walker) < 0) {
|
|
- walker->stop = 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
-ignore:
|
|
- walker->count++;
|
|
- }
|
|
-}
|
|
-
|
|
-static struct tcf_block *dsmark_tcf_block(struct Qdisc *sch, unsigned long cl)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
-
|
|
- return p->block;
|
|
-}
|
|
-
|
|
-/* --------------------------- Qdisc operations ---------------------------- */
|
|
-
|
|
-static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|
- struct sk_buff **to_free)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
- int err;
|
|
-
|
|
- pr_debug("%s(skb %p,sch %p,[qdisc %p])\n", __func__, skb, sch, p);
|
|
-
|
|
- if (p->set_tc_index) {
|
|
- int wlen = skb_network_offset(skb);
|
|
-
|
|
- switch (tc_skb_protocol(skb)) {
|
|
- case htons(ETH_P_IP):
|
|
- wlen += sizeof(struct iphdr);
|
|
- if (!pskb_may_pull(skb, wlen) ||
|
|
- skb_try_make_writable(skb, wlen))
|
|
- goto drop;
|
|
-
|
|
- skb->tc_index = ipv4_get_dsfield(ip_hdr(skb))
|
|
- & ~INET_ECN_MASK;
|
|
- break;
|
|
-
|
|
- case htons(ETH_P_IPV6):
|
|
- wlen += sizeof(struct ipv6hdr);
|
|
- if (!pskb_may_pull(skb, wlen) ||
|
|
- skb_try_make_writable(skb, wlen))
|
|
- goto drop;
|
|
-
|
|
- skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb))
|
|
- & ~INET_ECN_MASK;
|
|
- break;
|
|
- default:
|
|
- skb->tc_index = 0;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (TC_H_MAJ(skb->priority) == sch->handle)
|
|
- skb->tc_index = TC_H_MIN(skb->priority);
|
|
- else {
|
|
- struct tcf_result res;
|
|
- struct tcf_proto *fl = rcu_dereference_bh(p->filter_list);
|
|
- int result = tcf_classify(skb, fl, &res, false);
|
|
-
|
|
- pr_debug("result %d class 0x%04x\n", result, res.classid);
|
|
-
|
|
- switch (result) {
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
- case TC_ACT_QUEUED:
|
|
- case TC_ACT_STOLEN:
|
|
- case TC_ACT_TRAP:
|
|
- __qdisc_drop(skb, to_free);
|
|
- return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
|
|
-
|
|
- case TC_ACT_SHOT:
|
|
- goto drop;
|
|
-#endif
|
|
- case TC_ACT_OK:
|
|
- skb->tc_index = TC_H_MIN(res.classid);
|
|
- break;
|
|
-
|
|
- default:
|
|
- if (p->default_index != NO_DEFAULT_INDEX)
|
|
- skb->tc_index = p->default_index;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- err = qdisc_enqueue(skb, p->q, to_free);
|
|
- if (err != NET_XMIT_SUCCESS) {
|
|
- if (net_xmit_drop_count(err))
|
|
- qdisc_qstats_drop(sch);
|
|
- return err;
|
|
- }
|
|
-
|
|
- qdisc_qstats_backlog_inc(sch, skb);
|
|
- sch->q.qlen++;
|
|
-
|
|
- return NET_XMIT_SUCCESS;
|
|
-
|
|
-drop:
|
|
- qdisc_drop(skb, sch, to_free);
|
|
- return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
|
|
-}
|
|
-
|
|
-static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
- struct sk_buff *skb;
|
|
- u32 index;
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
|
|
-
|
|
- skb = qdisc_dequeue_peeked(p->q);
|
|
- if (skb == NULL)
|
|
- return NULL;
|
|
-
|
|
- qdisc_bstats_update(sch, skb);
|
|
- qdisc_qstats_backlog_dec(sch, skb);
|
|
- sch->q.qlen--;
|
|
-
|
|
- index = skb->tc_index & (p->indices - 1);
|
|
- pr_debug("index %d->%d\n", skb->tc_index, index);
|
|
-
|
|
- switch (tc_skb_protocol(skb)) {
|
|
- case htons(ETH_P_IP):
|
|
- ipv4_change_dsfield(ip_hdr(skb), p->mv[index].mask,
|
|
- p->mv[index].value);
|
|
- break;
|
|
- case htons(ETH_P_IPV6):
|
|
- ipv6_change_dsfield(ipv6_hdr(skb), p->mv[index].mask,
|
|
- p->mv[index].value);
|
|
- break;
|
|
- default:
|
|
- /*
|
|
- * Only complain if a change was actually attempted.
|
|
- * This way, we can send non-IP traffic through dsmark
|
|
- * and don't need yet another qdisc as a bypass.
|
|
- */
|
|
- if (p->mv[index].mask != 0xff || p->mv[index].value)
|
|
- pr_warn("%s: unsupported protocol %d\n",
|
|
- __func__, ntohs(tc_skb_protocol(skb)));
|
|
- break;
|
|
- }
|
|
-
|
|
- return skb;
|
|
-}
|
|
-
|
|
-static struct sk_buff *dsmark_peek(struct Qdisc *sch)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
|
|
-
|
|
- return p->q->ops->peek(p->q);
|
|
-}
|
|
-
|
|
-static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
- struct nlattr *tb[TCA_DSMARK_MAX + 1];
|
|
- int err = -EINVAL;
|
|
- u32 default_index = NO_DEFAULT_INDEX;
|
|
- u16 indices;
|
|
- int i;
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p],opt %p)\n", __func__, sch, p, opt);
|
|
-
|
|
- if (!opt)
|
|
- goto errout;
|
|
-
|
|
- err = tcf_block_get(&p->block, &p->filter_list);
|
|
- if (err)
|
|
- return err;
|
|
-
|
|
- err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy, NULL);
|
|
- if (err < 0)
|
|
- goto errout;
|
|
-
|
|
- err = -EINVAL;
|
|
- if (!tb[TCA_DSMARK_INDICES])
|
|
- goto errout;
|
|
- indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
|
|
-
|
|
- if (hweight32(indices) != 1)
|
|
- goto errout;
|
|
-
|
|
- if (tb[TCA_DSMARK_DEFAULT_INDEX])
|
|
- default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
|
|
-
|
|
- if (indices <= DSMARK_EMBEDDED_SZ)
|
|
- p->mv = p->embedded;
|
|
- else
|
|
- p->mv = kmalloc_array(indices, sizeof(*p->mv), GFP_KERNEL);
|
|
- if (!p->mv) {
|
|
- err = -ENOMEM;
|
|
- goto errout;
|
|
- }
|
|
- for (i = 0; i < indices; i++) {
|
|
- p->mv[i].mask = 0xff;
|
|
- p->mv[i].value = 0;
|
|
- }
|
|
- p->indices = indices;
|
|
- p->default_index = default_index;
|
|
- p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]);
|
|
-
|
|
- p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle);
|
|
- if (p->q == NULL)
|
|
- p->q = &noop_qdisc;
|
|
- else
|
|
- qdisc_hash_add(p->q, true);
|
|
-
|
|
- pr_debug("%s: qdisc %p\n", __func__, p->q);
|
|
-
|
|
- err = 0;
|
|
-errout:
|
|
- return err;
|
|
-}
|
|
-
|
|
-static void dsmark_reset(struct Qdisc *sch)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
|
|
- if (p->q)
|
|
- qdisc_reset(p->q);
|
|
- sch->qstats.backlog = 0;
|
|
- sch->q.qlen = 0;
|
|
-}
|
|
-
|
|
-static void dsmark_destroy(struct Qdisc *sch)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
|
|
-
|
|
- tcf_block_put(p->block);
|
|
- qdisc_destroy(p->q);
|
|
- if (p->mv != p->embedded)
|
|
- kfree(p->mv);
|
|
-}
|
|
-
|
|
-static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
|
|
- struct sk_buff *skb, struct tcmsg *tcm)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
- struct nlattr *opts = NULL;
|
|
-
|
|
- pr_debug("%s(sch %p,[qdisc %p],class %ld\n", __func__, sch, p, cl);
|
|
-
|
|
- if (!dsmark_valid_index(p, cl))
|
|
- return -EINVAL;
|
|
-
|
|
- tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl - 1);
|
|
- tcm->tcm_info = p->q->handle;
|
|
-
|
|
- opts = nla_nest_start(skb, TCA_OPTIONS);
|
|
- if (opts == NULL)
|
|
- goto nla_put_failure;
|
|
- if (nla_put_u8(skb, TCA_DSMARK_MASK, p->mv[cl - 1].mask) ||
|
|
- nla_put_u8(skb, TCA_DSMARK_VALUE, p->mv[cl - 1].value))
|
|
- goto nla_put_failure;
|
|
-
|
|
- return nla_nest_end(skb, opts);
|
|
-
|
|
-nla_put_failure:
|
|
- nla_nest_cancel(skb, opts);
|
|
- return -EMSGSIZE;
|
|
-}
|
|
-
|
|
-static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
|
|
-{
|
|
- struct dsmark_qdisc_data *p = qdisc_priv(sch);
|
|
- struct nlattr *opts = NULL;
|
|
-
|
|
- opts = nla_nest_start(skb, TCA_OPTIONS);
|
|
- if (opts == NULL)
|
|
- goto nla_put_failure;
|
|
- if (nla_put_u16(skb, TCA_DSMARK_INDICES, p->indices))
|
|
- goto nla_put_failure;
|
|
-
|
|
- if (p->default_index != NO_DEFAULT_INDEX &&
|
|
- nla_put_u16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index))
|
|
- goto nla_put_failure;
|
|
-
|
|
- if (p->set_tc_index &&
|
|
- nla_put_flag(skb, TCA_DSMARK_SET_TC_INDEX))
|
|
- goto nla_put_failure;
|
|
-
|
|
- return nla_nest_end(skb, opts);
|
|
-
|
|
-nla_put_failure:
|
|
- nla_nest_cancel(skb, opts);
|
|
- return -EMSGSIZE;
|
|
-}
|
|
-
|
|
-static const struct Qdisc_class_ops dsmark_class_ops = {
|
|
- .graft = dsmark_graft,
|
|
- .leaf = dsmark_leaf,
|
|
- .find = dsmark_find,
|
|
- .change = dsmark_change,
|
|
- .delete = dsmark_delete,
|
|
- .walk = dsmark_walk,
|
|
- .tcf_block = dsmark_tcf_block,
|
|
- .bind_tcf = dsmark_bind_filter,
|
|
- .unbind_tcf = dsmark_unbind_filter,
|
|
- .dump = dsmark_dump_class,
|
|
-};
|
|
-
|
|
-static struct Qdisc_ops dsmark_qdisc_ops __read_mostly = {
|
|
- .next = NULL,
|
|
- .cl_ops = &dsmark_class_ops,
|
|
- .id = "dsmark",
|
|
- .priv_size = sizeof(struct dsmark_qdisc_data),
|
|
- .enqueue = dsmark_enqueue,
|
|
- .dequeue = dsmark_dequeue,
|
|
- .peek = dsmark_peek,
|
|
- .init = dsmark_init,
|
|
- .reset = dsmark_reset,
|
|
- .destroy = dsmark_destroy,
|
|
- .change = NULL,
|
|
- .dump = dsmark_dump,
|
|
- .owner = THIS_MODULE,
|
|
-};
|
|
-
|
|
-static int __init dsmark_module_init(void)
|
|
-{
|
|
- return register_qdisc(&dsmark_qdisc_ops);
|
|
-}
|
|
-
|
|
-static void __exit dsmark_module_exit(void)
|
|
-{
|
|
- unregister_qdisc(&dsmark_qdisc_ops);
|
|
-}
|
|
-
|
|
-module_init(dsmark_module_init)
|
|
-module_exit(dsmark_module_exit)
|
|
-
|
|
-MODULE_LICENSE("GPL");
|
|
diff --git net/sunrpc/xprtmultipath.c net/sunrpc/xprtmultipath.c
|
|
index e2d64c7138c3..699d5ba128fa 100644
|
|
--- net/sunrpc/xprtmultipath.c
|
|
+++ net/sunrpc/xprtmultipath.c
|
|
@@ -235,8 +235,9 @@ struct rpc_xprt *xprt_iter_current_entry(struct rpc_xprt_iter *xpi)
|
|
return xprt_switch_find_current_entry(head, xpi->xpi_cursor);
|
|
}
|
|
|
|
-bool rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps,
|
|
- const struct sockaddr *sap)
|
|
+static
|
|
+bool __rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps,
|
|
+ const struct sockaddr *sap)
|
|
{
|
|
struct list_head *head;
|
|
struct rpc_xprt *pos;
|
|
@@ -255,6 +256,18 @@ bool rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps,
|
|
return false;
|
|
}
|
|
|
|
+bool rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps,
|
|
+ const struct sockaddr *sap)
|
|
+{
|
|
+ bool res;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ res = __rpc_xprt_switch_has_addr(xps, sap);
|
|
+ rcu_read_unlock();
|
|
+
|
|
+ return res;
|
|
+}
|
|
+
|
|
static
|
|
struct rpc_xprt *xprt_switch_find_next_entry(struct list_head *head,
|
|
const struct rpc_xprt *cur)
|
|
diff --git net/tipc/bearer.c net/tipc/bearer.c
|
|
index 506cbd1b2223..db21e00806f5 100644
|
|
--- net/tipc/bearer.c
|
|
+++ net/tipc/bearer.c
|
|
@@ -931,6 +931,12 @@ int tipc_nl_bearer_add(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
#ifdef CONFIG_TIPC_MEDIA_UDP
|
|
if (attrs[TIPC_NLA_BEARER_UDP_OPTS]) {
|
|
+ if (b->media->type_id != TIPC_MEDIA_TYPE_UDP) {
|
|
+ rtnl_unlock();
|
|
+ NL_SET_ERR_MSG(info->extack, "UDP option is unsupported");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
err = tipc_udp_nl_bearer_add(b,
|
|
attrs[TIPC_NLA_BEARER_UDP_OPTS]);
|
|
if (err) {
|
|
diff --git net/unix/af_unix.c net/unix/af_unix.c
|
|
index 8d25d50f916e..b1855778acd0 100644
|
|
--- net/unix/af_unix.c
|
|
+++ net/unix/af_unix.c
|
|
@@ -1127,13 +1127,11 @@ static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
|
|
unix_state_lock(sk1);
|
|
return;
|
|
}
|
|
- if (sk1 < sk2) {
|
|
- unix_state_lock(sk1);
|
|
- unix_state_lock_nested(sk2);
|
|
- } else {
|
|
- unix_state_lock(sk2);
|
|
- unix_state_lock_nested(sk1);
|
|
- }
|
|
+ if (sk1 > sk2)
|
|
+ swap(sk1, sk2);
|
|
+
|
|
+ unix_state_lock(sk1);
|
|
+ unix_state_lock_nested(sk2, U_LOCK_SECOND);
|
|
}
|
|
|
|
static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
|
|
@@ -1352,7 +1350,7 @@ restart:
|
|
goto out_unlock;
|
|
}
|
|
|
|
- unix_state_lock_nested(sk);
|
|
+ unix_state_lock_nested(sk, U_LOCK_SECOND);
|
|
|
|
if (sk->sk_state != st) {
|
|
unix_state_unlock(sk);
|
|
diff --git net/unix/diag.c net/unix/diag.c
|
|
index 3183d9b8ab33..d6ceac688def 100644
|
|
--- net/unix/diag.c
|
|
+++ net/unix/diag.c
|
|
@@ -80,7 +80,7 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)
|
|
* queue lock. With the other's queue locked it's
|
|
* OK to lock the state.
|
|
*/
|
|
- unix_state_lock_nested(req);
|
|
+ unix_state_lock_nested(req, U_LOCK_DIAG);
|
|
peer = unix_sk(req)->peer;
|
|
buf[i++] = (peer ? sock_i_ino(peer) : 0);
|
|
unix_state_unlock(req);
|
|
diff --git net/wireless/nl80211.c net/wireless/nl80211.c
|
|
index b4b564182db0..4f43f4dfb996 100644
|
|
--- net/wireless/nl80211.c
|
|
+++ net/wireless/nl80211.c
|
|
@@ -2717,6 +2717,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|
if_idx++;
|
|
}
|
|
|
|
+ if_start = 0;
|
|
wp_idx++;
|
|
}
|
|
out:
|
|
@@ -2896,6 +2897,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
if (ntype != NL80211_IFTYPE_MESH_POINT)
|
|
return -EINVAL;
|
|
+ if (otype != NL80211_IFTYPE_MESH_POINT)
|
|
+ return -EINVAL;
|
|
if (netif_running(dev))
|
|
return -EBUSY;
|
|
|
|
diff --git net/wireless/scan.c net/wireless/scan.c
|
|
index 8bbcdcf5c829..88fe0e8e8b18 100644
|
|
--- net/wireless/scan.c
|
|
+++ net/wireless/scan.c
|
|
@@ -1015,8 +1015,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
|
list_add(&new->hidden_list,
|
|
&hidden->hidden_list);
|
|
hidden->refcount++;
|
|
+
|
|
+ ies = (void *)rcu_access_pointer(new->pub.beacon_ies);
|
|
rcu_assign_pointer(new->pub.beacon_ies,
|
|
hidden->pub.beacon_ies);
|
|
+ if (ies)
|
|
+ kfree_rcu(ies, rcu_head);
|
|
}
|
|
} else {
|
|
/*
|
|
diff --git security/apparmor/policy_unpack.c security/apparmor/policy_unpack.c
|
|
index 2cef8d4404cc..4f41aa6ff897 100644
|
|
--- security/apparmor/policy_unpack.c
|
|
+++ security/apparmor/policy_unpack.c
|
|
@@ -604,6 +604,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
|
|
|
|
tmpname = aa_splitn_fqname(name, strlen(name), &tmpns, &ns_len);
|
|
if (tmpns) {
|
|
+ if (!tmpname) {
|
|
+ info = "empty profile name";
|
|
+ goto fail;
|
|
+ }
|
|
*ns_name = kstrndup(tmpns, ns_len, GFP_KERNEL);
|
|
if (!*ns_name) {
|
|
info = "out of memory";
|
|
diff --git security/security.c security/security.c
|
|
index b5e3d7a91b33..90c2094380e2 100644
|
|
--- security/security.c
|
|
+++ security/security.c
|
|
@@ -884,6 +884,23 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
return call_int_hook(file_ioctl, 0, file, cmd, arg);
|
|
}
|
|
|
|
+/**
|
|
+ * security_file_ioctl_compat() - Check if an ioctl is allowed in compat mode
|
|
+ * @file: associated file
|
|
+ * @cmd: ioctl cmd
|
|
+ * @arg: ioctl arguments
|
|
+ *
|
|
+ * Compat version of security_file_ioctl() that correctly handles 32-bit
|
|
+ * processes running on 64-bit kernels.
|
|
+ *
|
|
+ * Return: Returns 0 if permission is granted.
|
|
+ */
|
|
+int security_file_ioctl_compat(struct file *file, unsigned int cmd,
|
|
+ unsigned long arg)
|
|
+{
|
|
+ return call_int_hook(file_ioctl_compat, 0, file, cmd, arg);
|
|
+}
|
|
+
|
|
static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
|
|
{
|
|
/*
|
|
diff --git security/selinux/hooks.c security/selinux/hooks.c
|
|
index 38a4db1f3aaa..a1613e22a734 100644
|
|
--- security/selinux/hooks.c
|
|
+++ security/selinux/hooks.c
|
|
@@ -3571,6 +3571,33 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
|
|
return error;
|
|
}
|
|
|
|
+static int selinux_file_ioctl_compat(struct file *file, unsigned int cmd,
|
|
+ unsigned long arg)
|
|
+{
|
|
+ /*
|
|
+ * If we are in a 64-bit kernel running 32-bit userspace, we need to
|
|
+ * make sure we don't compare 32-bit flags to 64-bit flags.
|
|
+ */
|
|
+ switch (cmd) {
|
|
+ case FS_IOC32_GETFLAGS:
|
|
+ cmd = FS_IOC_GETFLAGS;
|
|
+ break;
|
|
+ case FS_IOC32_SETFLAGS:
|
|
+ cmd = FS_IOC_SETFLAGS;
|
|
+ break;
|
|
+ case FS_IOC32_GETVERSION:
|
|
+ cmd = FS_IOC_GETVERSION;
|
|
+ break;
|
|
+ case FS_IOC32_SETVERSION:
|
|
+ cmd = FS_IOC_SETVERSION;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return selinux_file_ioctl(file, cmd, arg);
|
|
+}
|
|
+
|
|
static int default_noexec;
|
|
|
|
static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
|
|
@@ -6377,6 +6404,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
|
|
LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
|
|
LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
|
|
LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
|
|
+ LSM_HOOK_INIT(file_ioctl_compat, selinux_file_ioctl_compat),
|
|
LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
|
|
LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
|
|
LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
|
|
diff --git security/smack/smack_lsm.c security/smack/smack_lsm.c
|
|
index fe070669dc18..a6e81ef73b42 100644
|
|
--- security/smack/smack_lsm.c
|
|
+++ security/smack/smack_lsm.c
|
|
@@ -4651,6 +4651,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
|
|
LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security),
|
|
LSM_HOOK_INIT(file_free_security, smack_file_free_security),
|
|
LSM_HOOK_INIT(file_ioctl, smack_file_ioctl),
|
|
+ LSM_HOOK_INIT(file_ioctl_compat, smack_file_ioctl),
|
|
LSM_HOOK_INIT(file_lock, smack_file_lock),
|
|
LSM_HOOK_INIT(file_fcntl, smack_file_fcntl),
|
|
LSM_HOOK_INIT(mmap_file, smack_mmap_file),
|
|
diff --git security/tomoyo/tomoyo.c security/tomoyo/tomoyo.c
|
|
index 213b8c593668..195f9b706926 100644
|
|
--- security/tomoyo/tomoyo.c
|
|
+++ security/tomoyo/tomoyo.c
|
|
@@ -516,6 +516,7 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
|
|
LSM_HOOK_INIT(path_rename, tomoyo_path_rename),
|
|
LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr),
|
|
LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl),
|
|
+ LSM_HOOK_INIT(file_ioctl_compat, tomoyo_file_ioctl),
|
|
LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod),
|
|
LSM_HOOK_INIT(path_chown, tomoyo_path_chown),
|
|
LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot),
|
|
diff --git sound/core/Makefile sound/core/Makefile
|
|
index ee4a4a6b99ba..753bf1a0dbf3 100644
|
|
--- sound/core/Makefile
|
|
+++ sound/core/Makefile
|
|
@@ -30,7 +30,6 @@ snd-pcm-dmaengine-objs := pcm_dmaengine.o
|
|
snd-rawmidi-objs := rawmidi.o
|
|
snd-timer-objs := timer.o
|
|
snd-hrtimer-objs := hrtimer.o
|
|
-snd-rtctimer-objs := rtctimer.o
|
|
snd-hwdep-objs := hwdep.o
|
|
snd-seq-device-objs := seq_device.o
|
|
|
|
diff --git sound/pci/hda/hda_intel.c sound/pci/hda/hda_intel.c
|
|
index 978719fc4cd3..bb76b9c26da8 100644
|
|
--- sound/pci/hda/hda_intel.c
|
|
+++ sound/pci/hda/hda_intel.c
|
|
@@ -2545,6 +2545,12 @@ static const struct pci_device_id azx_ids[] = {
|
|
/* Cannonlake */
|
|
{ PCI_DEVICE(0x8086, 0x9dc8),
|
|
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
|
+ /* Icelake */
|
|
+ { PCI_DEVICE(0x8086, 0x34c8),
|
|
+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
|
+ /* Arrow Lake */
|
|
+ { PCI_DEVICE(0x8086, 0x7728),
|
|
+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
|
/* Broxton-P(Apollolake) */
|
|
{ PCI_DEVICE(0x8086, 0x5a98),
|
|
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON },
|
|
diff --git sound/pci/hda/patch_conexant.c sound/pci/hda/patch_conexant.c
|
|
index 9263cb56df7d..6215d85428c7 100644
|
|
--- sound/pci/hda/patch_conexant.c
|
|
+++ sound/pci/hda/patch_conexant.c
|
|
@@ -263,6 +263,7 @@ enum {
|
|
CXT_FIXUP_MUTE_LED_GPIO,
|
|
CXT_FIXUP_HEADSET_MIC,
|
|
CXT_FIXUP_HP_MIC_NO_PRESENCE,
|
|
+ CXT_PINCFG_SWS_JS201D,
|
|
};
|
|
|
|
/* for hda_fixup_thinkpad_acpi() */
|
|
@@ -754,6 +755,17 @@ static const struct hda_pintbl cxt_pincfg_lemote[] = {
|
|
{}
|
|
};
|
|
|
|
+/* SuoWoSi/South-holding JS201D with sn6140 */
|
|
+static const struct hda_pintbl cxt_pincfg_sws_js201d[] = {
|
|
+ { 0x16, 0x03211040 }, /* hp out */
|
|
+ { 0x17, 0x91170110 }, /* SPK/Class_D */
|
|
+ { 0x18, 0x95a70130 }, /* Internal mic */
|
|
+ { 0x19, 0x03a11020 }, /* Headset Mic */
|
|
+ { 0x1a, 0x40f001f0 }, /* Not used */
|
|
+ { 0x21, 0x40f001f0 }, /* Not used */
|
|
+ {}
|
|
+};
|
|
+
|
|
static const struct hda_fixup cxt_fixups[] = {
|
|
[CXT_PINCFG_LENOVO_X200] = {
|
|
.type = HDA_FIXUP_PINS,
|
|
@@ -905,6 +917,10 @@ static const struct hda_fixup cxt_fixups[] = {
|
|
.chained = true,
|
|
.chain_id = CXT_FIXUP_HEADSET_MIC,
|
|
},
|
|
+ [CXT_PINCFG_SWS_JS201D] = {
|
|
+ .type = HDA_FIXUP_PINS,
|
|
+ .v.pins = cxt_pincfg_sws_js201d,
|
|
+ },
|
|
};
|
|
|
|
static const struct snd_pci_quirk cxt5045_fixups[] = {
|
|
@@ -973,6 +989,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
|
|
SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO),
|
|
SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
|
|
+ SND_PCI_QUIRK(0x14f1, 0x0265, "SWS JS201D", CXT_PINCFG_SWS_JS201D),
|
|
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
|
|
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
|
|
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
|
|
@@ -1011,6 +1028,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
|
|
{ .id = CXT_FIXUP_HP_DOCK, .name = "hp-dock" },
|
|
{ .id = CXT_FIXUP_MUTE_LED_GPIO, .name = "mute-led-gpio" },
|
|
{ .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" },
|
|
+ { .id = CXT_PINCFG_SWS_JS201D, .name = "sws-js201d" },
|
|
{}
|
|
};
|
|
|
|
diff --git sound/pci/oxygen/oxygen_mixer.c sound/pci/oxygen/oxygen_mixer.c
|
|
index 4ca12665ff73..64a82688d7fb 100644
|
|
--- sound/pci/oxygen/oxygen_mixer.c
|
|
+++ sound/pci/oxygen/oxygen_mixer.c
|
|
@@ -730,7 +730,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
|
|
oldreg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN);
|
|
newreg = oldreg & ~0x0707;
|
|
newreg = newreg | (value->value.integer.value[0] & 7);
|
|
- newreg = newreg | ((value->value.integer.value[0] & 7) << 8);
|
|
+ newreg = newreg | ((value->value.integer.value[1] & 7) << 8);
|
|
change = newreg != oldreg;
|
|
if (change)
|
|
oxygen_write_ac97(chip, 1, AC97_REC_GAIN, newreg);
|
|
diff --git sound/soc/codecs/cs35l33.c sound/soc/codecs/cs35l33.c
|
|
index e2c1194ea61a..32048c4c7e71 100644
|
|
--- sound/soc/codecs/cs35l33.c
|
|
+++ sound/soc/codecs/cs35l33.c
|
|
@@ -26,13 +26,11 @@
|
|
#include <sound/soc-dapm.h>
|
|
#include <sound/initval.h>
|
|
#include <sound/tlv.h>
|
|
-#include <linux/gpio.h>
|
|
#include <linux/gpio/consumer.h>
|
|
#include <sound/cs35l33.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/regulator/machine.h>
|
|
-#include <linux/of_gpio.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/of_irq.h>
|
|
@@ -1173,7 +1171,7 @@ static int cs35l33_i2c_probe(struct i2c_client *i2c_client,
|
|
|
|
/* We could issue !RST or skip it based on AMP topology */
|
|
cs35l33->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
|
|
- "reset-gpios", GPIOD_OUT_HIGH);
|
|
+ "reset", GPIOD_OUT_HIGH);
|
|
if (IS_ERR(cs35l33->reset_gpio)) {
|
|
dev_err(&i2c_client->dev, "%s ERROR: Can't get reset GPIO\n",
|
|
__func__);
|
|
diff --git sound/soc/codecs/cs35l34.c sound/soc/codecs/cs35l34.c
|
|
index 1e05026bedca..8a0ca34d828e 100644
|
|
--- sound/soc/codecs/cs35l34.c
|
|
+++ sound/soc/codecs/cs35l34.c
|
|
@@ -24,14 +24,12 @@
|
|
#include <linux/regulator/machine.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/of_device.h>
|
|
-#include <linux/of_gpio.h>
|
|
#include <linux/of_irq.h>
|
|
#include <sound/core.h>
|
|
#include <sound/pcm.h>
|
|
#include <sound/pcm_params.h>
|
|
#include <sound/soc.h>
|
|
#include <sound/soc-dapm.h>
|
|
-#include <linux/gpio.h>
|
|
#include <linux/gpio/consumer.h>
|
|
#include <sound/initval.h>
|
|
#include <sound/tlv.h>
|
|
@@ -1068,7 +1066,7 @@ static int cs35l34_i2c_probe(struct i2c_client *i2c_client,
|
|
dev_err(&i2c_client->dev, "Failed to request IRQ: %d\n", ret);
|
|
|
|
cs35l34->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
|
|
- "reset-gpios", GPIOD_OUT_LOW);
|
|
+ "reset", GPIOD_OUT_LOW);
|
|
if (IS_ERR(cs35l34->reset_gpio))
|
|
return PTR_ERR(cs35l34->reset_gpio);
|
|
|
|
diff --git sound/soc/codecs/cs43130.c sound/soc/codecs/cs43130.c
|
|
index 643e37fc218e..ad5d527e6e52 100644
|
|
--- sound/soc/codecs/cs43130.c
|
|
+++ sound/soc/codecs/cs43130.c
|
|
@@ -581,7 +581,7 @@ static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk,
|
|
break;
|
|
case SND_SOC_DAIFMT_LEFT_J:
|
|
hi_size = bitwidth_sclk;
|
|
- frm_delay = 2;
|
|
+ frm_delay = 0;
|
|
frm_phase = 1;
|
|
break;
|
|
case SND_SOC_DAIFMT_DSP_A:
|
|
@@ -1675,7 +1675,7 @@ static ssize_t cs43130_show_dc_r(struct device *dev,
|
|
return cs43130_show_dc(dev, buf, HP_RIGHT);
|
|
}
|
|
|
|
-static u16 const cs43130_ac_freq[CS43130_AC_FREQ] = {
|
|
+static const u16 cs43130_ac_freq[CS43130_AC_FREQ] = {
|
|
24,
|
|
43,
|
|
93,
|
|
@@ -2351,7 +2351,7 @@ static const struct regmap_config cs43130_regmap = {
|
|
.use_single_rw = true, /* needed for regcache_sync */
|
|
};
|
|
|
|
-static u16 const cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {
|
|
+static const u16 cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {
|
|
50,
|
|
120,
|
|
};
|
|
diff --git sound/soc/codecs/da7219-aad.c sound/soc/codecs/da7219-aad.c
|
|
index 793c8768f7c4..5a31a4db1e23 100644
|
|
--- sound/soc/codecs/da7219-aad.c
|
|
+++ sound/soc/codecs/da7219-aad.c
|
|
@@ -650,7 +650,7 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_codec *cod
|
|
aad_pdata->mic_det_thr =
|
|
da7219_aad_fw_mic_det_thr(codec, fw_val32);
|
|
else
|
|
- aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS;
|
|
+ aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_200_OHMS;
|
|
|
|
if (fwnode_property_read_u32(aad_np, "dlg,jack-ins-deb", &fw_val32) >= 0)
|
|
aad_pdata->jack_ins_deb =
|
|
diff --git sound/soc/codecs/rt5645.c sound/soc/codecs/rt5645.c
|
|
index 822c42101c3f..536a33820265 100644
|
|
--- sound/soc/codecs/rt5645.c
|
|
+++ sound/soc/codecs/rt5645.c
|
|
@@ -417,6 +417,7 @@ struct rt5645_priv {
|
|
struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)];
|
|
struct rt5645_eq_param_s *eq_param;
|
|
struct timer_list btn_check_timer;
|
|
+ struct mutex jd_mutex;
|
|
|
|
int codec_type;
|
|
int sysclk;
|
|
@@ -3158,6 +3159,8 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
|
|
rt5645_enable_push_button_irq(codec, true);
|
|
}
|
|
} else {
|
|
+ if (rt5645->en_button_func)
|
|
+ rt5645_enable_push_button_irq(codec, false);
|
|
snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
|
|
snd_soc_dapm_sync(dapm);
|
|
rt5645->jack_type = SND_JACK_HEADPHONE;
|
|
@@ -3238,6 +3241,8 @@ static void rt5645_jack_detect_work(struct work_struct *work)
|
|
if (!rt5645->codec)
|
|
return;
|
|
|
|
+ mutex_lock(&rt5645->jd_mutex);
|
|
+
|
|
switch (rt5645->pdata.jd_mode) {
|
|
case 0: /* Not using rt5645 JD */
|
|
if (rt5645->gpiod_hp_det) {
|
|
@@ -3250,6 +3255,7 @@ static void rt5645_jack_detect_work(struct work_struct *work)
|
|
report, SND_JACK_HEADPHONE);
|
|
snd_soc_jack_report(rt5645->mic_jack,
|
|
report, SND_JACK_MICROPHONE);
|
|
+ mutex_unlock(&rt5645->jd_mutex);
|
|
return;
|
|
default: /* read rt5645 jd1_1 status */
|
|
val = snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x1000;
|
|
@@ -3259,7 +3265,7 @@ static void rt5645_jack_detect_work(struct work_struct *work)
|
|
|
|
if (!val && (rt5645->jack_type == 0)) { /* jack in */
|
|
report = rt5645_jack_detect(rt5645->codec, 1);
|
|
- } else if (!val && rt5645->jack_type != 0) {
|
|
+ } else if (!val && rt5645->jack_type == SND_JACK_HEADSET) {
|
|
/* for push button and jack out */
|
|
btn_type = 0;
|
|
if (snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x4) {
|
|
@@ -3315,6 +3321,8 @@ static void rt5645_jack_detect_work(struct work_struct *work)
|
|
rt5645_jack_detect(rt5645->codec, 0);
|
|
}
|
|
|
|
+ mutex_unlock(&rt5645->jd_mutex);
|
|
+
|
|
snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE);
|
|
snd_soc_jack_report(rt5645->mic_jack, report, SND_JACK_MICROPHONE);
|
|
if (rt5645->en_button_func)
|
|
@@ -3939,6 +3947,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
|
|
setup_timer(&rt5645->btn_check_timer,
|
|
rt5645_btn_check_callback, (unsigned long)rt5645);
|
|
|
|
+ mutex_init(&rt5645->jd_mutex);
|
|
INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work);
|
|
INIT_DELAYED_WORK(&rt5645->rcclock_work, rt5645_rcclock_work);
|
|
|
|
diff --git tools/lib/subcmd/help.c tools/lib/subcmd/help.c
|
|
index 2859f107abc8..4260c8b4257b 100644
|
|
--- tools/lib/subcmd/help.c
|
|
+++ tools/lib/subcmd/help.c
|
|
@@ -50,11 +50,21 @@ void uniq(struct cmdnames *cmds)
|
|
if (!cmds->cnt)
|
|
return;
|
|
|
|
- for (i = j = 1; i < cmds->cnt; i++)
|
|
- if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name))
|
|
- cmds->names[j++] = cmds->names[i];
|
|
-
|
|
+ for (i = 1; i < cmds->cnt; i++) {
|
|
+ if (!strcmp(cmds->names[i]->name, cmds->names[i-1]->name))
|
|
+ zfree(&cmds->names[i - 1]);
|
|
+ }
|
|
+ for (i = 0, j = 0; i < cmds->cnt; i++) {
|
|
+ if (cmds->names[i]) {
|
|
+ if (i == j)
|
|
+ j++;
|
|
+ else
|
|
+ cmds->names[j++] = cmds->names[i];
|
|
+ }
|
|
+ }
|
|
cmds->cnt = j;
|
|
+ while (j < i)
|
|
+ cmds->names[j++] = NULL;
|
|
}
|
|
|
|
void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
|
|
diff --git tools/testing/selftests/powerpc/math/fpu_preempt.c tools/testing/selftests/powerpc/math/fpu_preempt.c
|
|
index 0f85b79d883d..c91f3b36e884 100644
|
|
--- tools/testing/selftests/powerpc/math/fpu_preempt.c
|
|
+++ tools/testing/selftests/powerpc/math/fpu_preempt.c
|
|
@@ -41,19 +41,20 @@ __thread double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
|
|
int threads_starting;
|
|
int running;
|
|
|
|
-extern void preempt_fpu(double *darray, int *threads_starting, int *running);
|
|
+extern int preempt_fpu(double *darray, int *threads_starting, int *running);
|
|
|
|
void *preempt_fpu_c(void *p)
|
|
{
|
|
+ long rc;
|
|
int i;
|
|
+
|
|
srand(pthread_self());
|
|
for (i = 0; i < 21; i++)
|
|
darray[i] = rand();
|
|
|
|
- /* Test failed if it ever returns */
|
|
- preempt_fpu(darray, &threads_starting, &running);
|
|
+ rc = preempt_fpu(darray, &threads_starting, &running);
|
|
|
|
- return p;
|
|
+ return (void *)rc;
|
|
}
|
|
|
|
int test_preempt_fpu(void)
|
|
diff --git tools/testing/selftests/powerpc/math/vmx_preempt.c tools/testing/selftests/powerpc/math/vmx_preempt.c
|
|
index 9ef376c55b13..7ba95ceaaa50 100644
|
|
--- tools/testing/selftests/powerpc/math/vmx_preempt.c
|
|
+++ tools/testing/selftests/powerpc/math/vmx_preempt.c
|
|
@@ -41,19 +41,21 @@ __thread vector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
|
|
int threads_starting;
|
|
int running;
|
|
|
|
-extern void preempt_vmx(vector int *varray, int *threads_starting, int *running);
|
|
+extern int preempt_vmx(vector int *varray, int *threads_starting, int *running);
|
|
|
|
void *preempt_vmx_c(void *p)
|
|
{
|
|
int i, j;
|
|
+ long rc;
|
|
+
|
|
srand(pthread_self());
|
|
for (i = 0; i < 12; i++)
|
|
for (j = 0; j < 4; j++)
|
|
varray[i][j] = rand();
|
|
|
|
- /* Test fails if it ever returns */
|
|
- preempt_vmx(varray, &threads_starting, &running);
|
|
- return p;
|
|
+ rc = preempt_vmx(varray, &threads_starting, &running);
|
|
+
|
|
+ return (void *)rc;
|
|
}
|
|
|
|
int test_preempt_vmx(void)
|
|
diff --git virt/kvm/arm/vgic/vgic-its.c virt/kvm/arm/vgic/vgic-its.c
|
|
index fd25c2161060..a4398f58a830 100644
|
|
--- virt/kvm/arm/vgic/vgic-its.c
|
|
+++ virt/kvm/arm/vgic/vgic-its.c
|
|
@@ -424,6 +424,9 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
|
|
}
|
|
|
|
irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]);
|
|
+ if (!irq)
|
|
+ continue;
|
|
+
|
|
spin_lock(&irq->irq_lock);
|
|
irq->pending_latch = pendmask & (1U << bit_nr);
|
|
vgic_queue_irq_unlock(vcpu->kvm, irq);
|