KVM: s390: some vSIE and UCONTROL fixes

Fix some memory issues and some hangs in vSIE.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEoWuZBM6M3lCBSfTnuARItAMU6BMFAmoQPUMACgkQuARItAMU
 6BMpJRAAyGmcEwrT3uRaScd3eX6A23Wyb4gb0TzlYPXM4oQaQWhl0gl0fYmIPxFI
 plSONGrgQA8TtmElixt1ijVo0edp0PnPgdfol7fkzpImzmOgJAI130p1IQAh34rm
 pFjvhOmaGJSl66VnXe6lDzJCTErcrEEZ0X3BNsm3PO/DNYCvKwgzDz8nsjsZ2RPE
 BvLIUqOTgknq0VwkO0WBqTfuKL0N/FHt6xeqR2cOdtgBzHjsuXH3/5BL7rW+TLou
 hG/97py7x3ivTDrK/ktP6PHtO3H/goPhHta8xTH2ow9MjvUT+SrVyc/pfi9AEiA7
 zpA36g8ArqokzcaAFFlA/iINndjokgakhW0T0jgwFvb0Qntf6TAJ6UlL8bw+YOnq
 qbHumWX5SijFktULpOBKY0WmDXPgxUE6UorxNP4rvsw8LaIfyguIJHZzas0h2khw
 uOsySoMHRZjUA7P603fmqSZTfjb/e3bnqNvo0cJtdnSwzmjfuyYEJz1lhGaYkHsF
 t/QoRDGCeIu5N988xc4HSE/Rwzij7QT68whbRPotDJQYYRMIi22RRfG+krNYhSja
 vbVhVFOJJwiCF3/zzhhlDMS7smfs9RYXbG0QbPF5w7/hdcIpPLRxwg5/5k0t6T/M
 W7igzgYaUEjyMcNNQWAWUULj46icpzBFzst+W3c1V9lmZ/nr6H8=
 =Pewa
 -----END PGP SIGNATURE-----

Merge tag 'kvm-s390-master-7.1-2' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

KVM: s390: some vSIE and UCONTROL fixes

Fix some memory issues and some hangs in vSIE.
This commit is contained in:
Paolo Bonzini 2026-05-23 10:03:58 +02:00
commit 37f32d5ab8
343 changed files with 6531 additions and 2149 deletions

View File

@ -584,6 +584,8 @@ Mayuresh Janorkar <mayur@ti.com>
Md Sadre Alam <quic_mdalam@quicinc.com> <mdalam@codeaurora.org>
Miaoqing Pan <quic_miaoqing@quicinc.com> <miaoqing@codeaurora.org>
Michael Buesch <m@bues.ch>
Michal Grzeschik <mgr@kernel.org> <m.grzeschik@pengutronix.de>
Michal Grzeschik <mgr@kernel.org> <mgr@pengutronix.de>
Michael Riesch <michael.riesch@collabora.com> <michael.riesch@wolfvision.net>
Michal Simek <michal.simek@amd.com> <michal.simek@xilinx.com>
Michel Dänzer <michel@tungstengraphics.com>

View File

@ -786,6 +786,7 @@ networking/altera_tse networking/device_drivers/ethernet/altera/altera_tse
networking/bpf_flow_dissector bpf/prog_flow_dissector
networking/cxacru networking/device_drivers/atm/cxacru
networking/defza networking/device_drivers/fddi/defza
networking/device_drivers/3com/3c509 networking/device_drivers/ethernet/3com/3c509
networking/device_drivers/3com/vortex networking/device_drivers/ethernet/3com/vortex
networking/device_drivers/amazon/ena networking/device_drivers/ethernet/amazon/ena
networking/device_drivers/aquantia/atlantic networking/device_drivers/ethernet/aquantia/atlantic

View File

@ -158,13 +158,22 @@ returned.
When a message has been received, the location and size of the data with the
message can be determined by calling::
void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len);
int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len);
The caller provides the offset and length of the message to the function, which
then alters those values to indicate the region containing the data (plus any
padding). It is up to the caller to determine how much padding there is.
padding). It is up to the caller to determine how much padding there is. The
function returns an error if the length is too small or if the mode is
unsupported. An additional function::
int crypto_krb5_check_data_len(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t len, size_t min_content);
is provided to just do a basic check that the decrypted/verified message would
have a sufficient minimum payload.
Preparation Functions
---------------------

View File

@ -73,6 +73,15 @@ properties:
HSP CSR is to control and get status of different high-speed peripherals
(such as Ethernet, USB, SATA, etc.) via register, which can tune
board-level's parameters of PHY, etc.
Additional background information about the High-Speed Subsystem
and the HSP CSR block is available in Chapter 10 ("High-Speed Interface")
of the EIC7700X SoC Technical Reference Manual, Part 4
(EIC7700X_SoC_Technical_Reference_Manual_Part4.pdf). The manual is
publicly available at
https://github.com/eswincomputing/EIC7700X-SoC-Technical-Reference-Manual/releases
This reference is provided for background information only.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
@ -82,6 +91,8 @@ properties:
- description: Offset of AXI clock controller Low-Power request
register
- description: Offset of register controlling TX/RX clock delay
- description: Optional offset of register controlling TXD delay
- description: Optional offset of register controlling RXD delay
required:
- compatible
@ -116,7 +127,7 @@ examples:
reset-names = "stmmaceth";
rx-internal-delay-ps = <200>;
tx-internal-delay-ps = <200>;
eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118>;
eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118 0x114 0x11c>;
snps,axi-config = <&stmmac_axi_setup>;
snps,aal;
snps,fixed-burst;

View File

@ -0,0 +1,249 @@
.. SPDX-License-Identifier: GPL-2.0
=============================================================================
Linux and the 3Com EtherLink III Series Ethercards (driver v1.18c and higher)
=============================================================================
This file contains the instructions and caveats for v1.18c and higher versions
of the 3c509 driver. You should not use the driver without reading this file.
release 1.0
28 February 2002
Current maintainer (corrections to):
Maciej W. Rozycki <macro@orcam.me.uk>
Introduction
============
The following are notes and information on using the 3Com EtherLink III series
ethercards in Linux. These cards are commonly known by the most widely-used
card's 3Com model number, 3c509. They are all 10mb/s ISA-bus cards and shouldn't
be (but sometimes are) confused with the similarly-numbered PCI-bus "3c905"
(aka "Vortex" or "Boomerang") series. Kernel support for the 3c509 family is
provided by the module 3c509.c, which has code to support all of the following
models:
- 3c509 (original ISA card)
- 3c509B (later revision of the ISA card; supports full-duplex)
- 3c589 (PCMCIA)
- 3c589B (later revision of the 3c589; supports full-duplex)
- 3c579 (EISA)
Large portions of this documentation were heavily borrowed from the guide
written the original author of the 3c509 driver, Donald Becker. The master
copy of that document, which contains notes on older versions of the driver,
currently resides on Scyld web server: http://www.scyld.com/.
Special Driver Features
=======================
Overriding card settings
The driver allows boot- or load-time overriding of the card's detected IOADDR,
IRQ, and transceiver settings, although this capability shouldn't generally be
needed except to enable full-duplex mode (see below). An example of the syntax
for LILO parameters for doing this::
ether=10,0x310,3,0x3c509,eth0
This configures the first found 3c509 card for IRQ 10, base I/O 0x310, and
transceiver type 3 (10base2). The flag "0x3c509" must be set to avoid conflicts
with other card types when overriding the I/O address. When the driver is
loaded as a module, only the IRQ may be overridden. For example,
setting two cards to IRQ10 and IRQ11 is done by using the irq module
option::
options 3c509 irq=10,11
Full-duplex mode
================
The v1.18c driver added support for the 3c509B's full-duplex capabilities.
In order to enable and successfully use full-duplex mode, three conditions
must be met:
(a) You must have a Etherlink III card model whose hardware supports full-
duplex operations. Currently, the only members of the 3c509 family that are
positively known to support full-duplex are the 3c509B (ISA bus) and 3c589B
(PCMCIA) cards. Cards without the "B" model designation do *not* support
full-duplex mode; these include the original 3c509 (no "B"), the original
3c589, the 3c529 (MCA bus), and the 3c579 (EISA bus).
(b) You must be using your card's 10baseT transceiver (i.e., the RJ-45
connector), not its AUI (thick-net) or 10base2 (thin-net/coax) interfaces.
AUI and 10base2 network cabling is physically incapable of full-duplex
operation.
(c) Most importantly, your 3c509B must be connected to a link partner that is
itself full-duplex capable. This is almost certainly one of two things: a full-
duplex-capable Ethernet switch (*not* a hub), or a full-duplex-capable NIC on
another system that's connected directly to the 3c509B via a crossover cable.
Full-duplex mode can be enabled using 'ethtool'.
.. warning::
Extremely important caution concerning full-duplex mode
Understand that the 3c509B's hardware's full-duplex support is much more
limited than that provide by more modern network interface cards. Although
at the physical layer of the network it fully supports full-duplex operation,
the card was designed before the current Ethernet auto-negotiation (N-way)
spec was written. This means that the 3c509B family ***cannot and will not
auto-negotiate a full-duplex connection with its link partner under any
circumstances, no matter how it is initialized***. If the full-duplex mode
of the 3c509B is enabled, its link partner will very likely need to be
independently _forced_ into full-duplex mode as well; otherwise various nasty
failures will occur - at the very least, you'll see massive numbers of packet
collisions. This is one of very rare circumstances where disabling auto-
negotiation and forcing the duplex mode of a network interface card or switch
would ever be necessary or desirable.
Available Transceiver Types
===========================
For versions of the driver v1.18c and above, the available transceiver types are:
== =========================================================================
0 transceiver type from EEPROM config (normally 10baseT); force half-duplex
1 AUI (thick-net / DB15 connector)
2 (undefined)
3 10base2 (thin-net == coax / BNC connector)
4 10baseT (RJ-45 connector); force half-duplex mode
8 transceiver type and duplex mode taken from card's EEPROM config settings
12 10baseT (RJ-45 connector); force full-duplex mode
== =========================================================================
Prior to driver version 1.18c, only transceiver codes 0-4 were supported. Note
that the new transceiver codes 8 and 12 are the *only* ones that will enable
full-duplex mode, no matter what the card's detected EEPROM settings might be.
This insured that merely upgrading the driver from an earlier version would
never automatically enable full-duplex mode in an existing installation;
it must always be explicitly enabled via one of these code in order to be
activated.
The transceiver type can be changed using 'ethtool'.
Interpretation of error messages and common problems
----------------------------------------------------
Error Messages
^^^^^^^^^^^^^^
eth0: Infinite loop in interrupt, status 2011.
These are "mostly harmless" message indicating that the driver had too much
work during that interrupt cycle. With a status of 0x2011 you are receiving
packets faster than they can be removed from the card. This should be rare
or impossible in normal operation. Possible causes of this error report are:
- a "green" mode enabled that slows the processor down when there is no
keyboard activity.
- some other device or device driver hogging the bus or disabling interrupts.
Check /proc/interrupts for excessive interrupt counts. The timer tick
interrupt should always be incrementing faster than the others.
No received packets
^^^^^^^^^^^^^^^^^^^
If a 3c509, 3c562 or 3c589 can successfully transmit packets, but never
receives packets (as reported by /proc/net/dev or 'ifconfig') you likely
have an interrupt line problem. Check /proc/interrupts to verify that the
card is actually generating interrupts. If the interrupt count is not
increasing you likely have a physical conflict with two devices trying to
use the same ISA IRQ line. The common conflict is with a sound card on IRQ10
or IRQ5, and the easiest solution is to move the 3c509 to a different
interrupt line. If the device is receiving packets but 'ping' doesn't work,
you have a routing problem.
Tx Carrier Errors Reported in /proc/net/dev
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If an EtherLink III appears to transmit packets, but the "Tx carrier errors"
field in /proc/net/dev increments as quickly as the Tx packet count, you
likely have an unterminated network or the incorrect media transceiver selected.
3c509B card is not detected on machines with an ISA PnP BIOS.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
While the updated driver works with most PnP BIOS programs, it does not work
with all. This can be fixed by disabling PnP support using the 3Com-supplied
setup program.
3c509 card is not detected on overclocked machines
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Increase the delay time in id_read_eeprom() from the current value, 500,
to an absurdly high value, such as 5000.
Decoding Status and Error Messages
----------------------------------
The bits in the main status register are:
===== ======================================
value description
===== ======================================
0x01 Interrupt latch
0x02 Tx overrun, or Rx underrun
0x04 Tx complete
0x08 Tx FIFO room available
0x10 A complete Rx packet has arrived
0x20 A Rx packet has started to arrive
0x40 The driver has requested an interrupt
0x80 Statistics counter nearly full
===== ======================================
The bits in the transmit (Tx) status word are:
===== ============================================
value description
===== ============================================
0x02 Out-of-window collision.
0x04 Status stack overflow (normally impossible).
0x08 16 collisions.
0x10 Tx underrun (not enough PCI bus bandwidth).
0x20 Tx jabber.
0x40 Tx interrupt requested.
0x80 Status is valid (this should always be set).
===== ============================================
When a transmit error occurs the driver produces a status message such as::
eth0: Transmit error, Tx status register 82
The two values typically seen here are:
0x82
^^^^
Out of window collision. This typically occurs when some other Ethernet
host is incorrectly set to full duplex on a half duplex network.
0x88
^^^^
16 collisions. This typically occurs when the network is exceptionally busy
or when another host doesn't correctly back off after a collision. If this
error is mixed with 0x82 errors it is the result of a host incorrectly set
to full duplex (see above).
Both of these errors are the result of network problems that should be
corrected. They do not represent driver malfunction.
Revision history (this file)
============================
28Feb02 v1.0 DR New; major portions based on Becker original 3c509 docs

View File

@ -10,6 +10,7 @@ Contents:
.. toctree::
:maxdepth: 2
3com/3c509
3com/vortex
amazon/ena
altera/altera_tse

View File

@ -2064,7 +2064,7 @@ F: Documentation/devicetree/bindings/display/snps,arcpgu.txt
F: drivers/gpu/drm/tiny/arcpgu.c
ARCNET NETWORK LAYER
M: Michael Grzeschik <m.grzeschik@pengutronix.de>
M: Michael Grzeschik <mgr@kernel.org>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/arcnet/
@ -3367,7 +3367,9 @@ F: drivers/irqchip/irq-rda-intc.c
F: drivers/tty/serial/rda-uart.c
ARM/REALTEK ARCHITECTURE
M: Andreas Färber <afaerber@suse.de>
M: James Tai <james.tai@realtek.com>
M: Yu-Chun Lin <eleanor.lin@realtek.com>
R: Andreas Färber <afaerber@suse.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-realtek-soc@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -3375,6 +3377,7 @@ F: Documentation/devicetree/bindings/arm/realtek.yaml
F: arch/arm/boot/dts/realtek/
F: arch/arm/mach-realtek/
F: arch/arm64/boot/dts/realtek/
F: drivers/pinctrl/realtek/
ARM/RISC-V/RENESAS ARCHITECTURE
M: Geert Uytterhoeven <geert+renesas@glider.be>
@ -13869,6 +13872,7 @@ M: Pratyush Yadav <pratyush@kernel.org>
R: Dave Young <ruirui.yang@linux.dev>
L: kexec@lists.infradead.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux.git
F: Documentation/admin-guide/kdump/
F: fs/proc/vmcore.c
F: include/linux/crash_core.h
@ -14186,6 +14190,7 @@ M: Pasha Tatashin <pasha.tatashin@soleen.com>
M: Pratyush Yadav <pratyush@kernel.org>
L: kexec@lists.infradead.org
W: http://kernel.org/pub/linux/utils/kernel/kexec/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux.git
F: include/linux/kexec.h
F: include/uapi/linux/kexec.h
F: kernel/kexec*
@ -14902,6 +14907,7 @@ LIVE UPDATE
M: Pasha Tatashin <pasha.tatashin@soleen.com>
M: Mike Rapoport <rppt@kernel.org>
M: Pratyush Yadav <pratyush@kernel.org>
L: kexec@lists.infradead.org
L: linux-kernel@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux.git
@ -18632,6 +18638,7 @@ F: tools/testing/selftests/net/
X: Documentation/networking/mac80211-injection.rst
X: Documentation/networking/mac80211_hwsim/
X: Documentation/networking/regulatory.rst
X: include/net/bluetooth/
X: include/net/cfg80211.h
X: include/net/ieee80211_radiotap.h
X: include/net/iw_handler.h
@ -20737,15 +20744,13 @@ F: Documentation/devicetree/bindings/pci/intel,keembay-pcie*
F: drivers/pci/controller/dwc/pcie-keembay.c
PCIE DRIVER FOR INTEL LGM GW SOC
M: Chuanhua Lei <lchuanhua@maxlinear.com>
L: linux-pci@vger.kernel.org
S: Maintained
S: Orphan
F: Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
F: drivers/pci/controller/dwc/pcie-intel-gw.c
PCIE DRIVER FOR MEDIATEK
M: Ryder Lee <ryder.lee@mediatek.com>
M: Jianjun Wang <jianjun.wang@mediatek.com>
L: linux-pci@vger.kernel.org
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Supported

View File

@ -5,4 +5,5 @@ generic-y += agp.h
generic-y += asm-offsets.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += text-patching.h

View File

@ -5,5 +5,6 @@ generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += text-patching.h

View File

@ -34,9 +34,6 @@ flash@18000000 {
clocks = <&mstp9_clks R7S72100_CLK_SPIBSC0>;
power-domains = <&cpg_clocks>;
#address-cells = <1>;
#size-cells = <1>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;

View File

@ -36,8 +36,6 @@ flash@18000000 {
power-domains = <&cpg_clocks>;
bank-width = <4>;
device-width = <1>;
#address-cells = <1>;
#size-cells = <1>;
partitions {
compatible = "fixed-partitions";

View File

@ -37,7 +37,7 @@ b_clk: b {
clock-div = <3>;
};
bsc: bus {
bsc: bus@0 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;

View File

@ -40,7 +40,7 @@ aliases {
spi2 = &hspi2;
};
lbsc: bus {
lbsc: bus@0 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;

View File

@ -704,7 +704,7 @@ R8A7779_CLK_MMC1 R8A7779_CLK_MMC0
};
};
lbsc: bus {
lbsc: bus@0 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;

View File

@ -86,7 +86,7 @@ extal_clk: extal {
bootph-all;
};
lbsc: bus {
lbsc: bus@0 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;

View File

@ -3,6 +3,7 @@ generic-y += early_ioremap.h
generic-y += extable.h
generic-y += flat.h
generic-y += parport.h
generic-y += ring_buffer.h
generated-y += mach-types.h
generated-y += unistd-nr.h

View File

@ -86,14 +86,6 @@ static u64 notrace intcp_read_sched_clock(void)
return val;
}
static void __init intcp_init_early(void)
{
cm_map = syscon_regmap_lookup_by_compatible("arm,core-module-integrator");
if (IS_ERR(cm_map))
return;
sched_clock_register(intcp_read_sched_clock, 32, 24000000);
}
static void __init intcp_init_irq_of(void)
{
cm_init();
@ -119,6 +111,10 @@ static void __init intcp_init_of(void)
{
struct device_node *cpcon;
cm_map = syscon_regmap_lookup_by_compatible("arm,core-module-integrator");
if (!IS_ERR(cm_map))
sched_clock_register(intcp_read_sched_clock, 32, 24000000);
cpcon = of_find_matching_node(NULL, intcp_syscon_match);
if (!cpcon)
return;
@ -138,7 +134,6 @@ static const char * intcp_dt_board_compat[] = {
DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
.reserve = integrator_reserve,
.map_io = intcp_map_io,
.init_early = intcp_init_early,
.init_irq = intcp_init_irq_of,
.init_machine = intcp_init_of,
.dt_compat = intcp_dt_board_compat,

View File

@ -27,7 +27,12 @@ &lvds1 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
lvds1_out: endpoint {
remote-endpoint = <&panel_in>;
};

View File

@ -699,7 +699,7 @@ scif0: serial@c0700000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0700000 0 0x40>;
interrupts = <GIC_ESPI 10 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
status = "disabled";
};
@ -709,7 +709,7 @@ scif1: serial@c0704000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0704000 0 0x40>;
interrupts = <GIC_ESPI 11 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
status = "disabled";
};
@ -719,7 +719,7 @@ scif3: serial@c0708000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0708000 0 0x40>;
interrupts = <GIC_ESPI 12 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
status = "disabled";
};
@ -729,7 +729,7 @@ scif4: serial@c070c000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc070c000 0 0x40>;
interrupts = <GIC_ESPI 13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
status = "disabled";
};

View File

@ -1327,6 +1327,7 @@ usb20phyrst: usb20phy-reset@15830000 {
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
#mux-state-cells = <1>;
status = "disabled";
};

View File

@ -1345,6 +1345,7 @@ usb20phyrst: usb20phy-reset@15830000 {
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
#mux-state-cells = <1>;
status = "disabled";
};
@ -1355,6 +1356,7 @@ usb21phyrst: usb21phy-reset@15840000 {
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
#mux-state-cells = <1>;
status = "disabled";
};

View File

@ -46,7 +46,12 @@ &csi2 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
csi2_in: endpoint {
clock-lanes = <0>;
data-lanes = <1 2>;

View File

@ -26,7 +26,12 @@ &du {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
du_out_rgb: endpoint {
remote-endpoint = <&adv7513_in>;
};

View File

@ -27,7 +27,12 @@ &lvds0 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
lvds0_out: endpoint {
remote-endpoint = <&panel_in>;
};

View File

@ -33,7 +33,7 @@ struct folio *vma_alloc_zeroed_movable_folio(struct vm_area_struct *vma,
unsigned long vaddr);
#define vma_alloc_zeroed_movable_folio vma_alloc_zeroed_movable_folio
bool tag_clear_highpages(struct page *to, int numpages);
bool tag_clear_highpages(struct page *to, int numpages, bool clear_pages);
#define __HAVE_ARCH_TAG_CLEAR_HIGHPAGES
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ASM_ARM64_RING_BUFFER_H
#define _ASM_ARM64_RING_BUFFER_H
#include <asm/cacheflush.h>
/* Flush D-cache on persistent ring buffer */
#define arch_ring_buffer_flush_range(start, end) dcache_clean_pop(start, end)
#endif /* _ASM_ARM64_RING_BUFFER_H */

View File

@ -1018,7 +1018,7 @@ struct folio *vma_alloc_zeroed_movable_folio(struct vm_area_struct *vma,
return vma_alloc_folio(flags, 0, vma, vaddr);
}
bool tag_clear_highpages(struct page *page, int numpages)
bool tag_clear_highpages(struct page *page, int numpages, bool clear_pages)
{
/*
* Check if MTE is supported and fall back to clear_highpage().
@ -1026,13 +1026,16 @@ bool tag_clear_highpages(struct page *page, int numpages)
* post_alloc_hook() will invoke tag_clear_highpages().
*/
if (!system_supports_mte())
return false;
return clear_pages;
/* Newly allocated pages, shouldn't have been tagged yet */
for (int i = 0; i < numpages; i++, page++) {
WARN_ON_ONCE(!try_page_mte_tagging(page));
mte_zero_clear_page_tags(page_address(page));
if (clear_pages)
mte_zero_clear_page_tags(page_address(page));
else
mte_clear_page_tags(page_address(page));
set_page_mte_tagged(page);
}
return true;
return false;
}

View File

@ -9,6 +9,7 @@ generic-y += qrwlock.h
generic-y += qrwlock_types.h
generic-y += qspinlock.h
generic-y += parport.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += vmlinux.lds.h
generic-y += text-patching.h

View File

@ -5,4 +5,5 @@ generic-y += extable.h
generic-y += iomap.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += text-patching.h

View File

@ -10,5 +10,6 @@ generic-y += qrwlock.h
generic-y += user.h
generic-y += ioctl.h
generic-y += mmzone.h
generic-y += ring_buffer.h
generic-y += statfs.h
generic-y += text-patching.h

View File

@ -3,5 +3,6 @@ generated-y += syscall_table.h
generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += spinlock.h
generic-y += text-patching.h

View File

@ -5,6 +5,7 @@ generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += ring_buffer.h
generic-y += syscalls.h
generic-y += tlb.h
generic-y += user.h

View File

@ -12,5 +12,6 @@ generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += qrwlock.h
generic-y += qspinlock.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += text-patching.h

View File

@ -5,6 +5,7 @@ generic-y += cmpxchg.h
generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += spinlock.h
generic-y += user.h
generic-y += text-patching.h

View File

@ -8,4 +8,5 @@ generic-y += spinlock_types.h
generic-y += spinlock.h
generic-y += qrwlock_types.h
generic-y += qrwlock.h
generic-y += ring_buffer.h
generic-y += user.h

View File

@ -4,4 +4,5 @@ generated-y += syscall_table_64.h
generic-y += agp.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += user.h

View File

@ -393,6 +393,7 @@ CONFIG_NETCONSOLE=m
CONFIG_TUN=m
CONFIG_VETH=m
CONFIG_VIRTIO_NET=m
CONFIG_EL3=m
CONFIG_VORTEX=m
CONFIG_TYPHOON=m
CONFIG_ADAPTEC_STARFIRE=m

View File

@ -5,4 +5,5 @@ generated-y += syscall_table_spu.h
generic-y += agp.h
generic-y += mcs_spinlock.h
generic-y += qrwlock.h
generic-y += ring_buffer.h
generic-y += early_ioremap.h

View File

@ -101,16 +101,6 @@ &ccc_nw {
status = "okay";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_fabric>;
};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_mssio>;
};
&mmuart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_fabric>;

View File

@ -14,6 +14,16 @@ / {
"microchip,mpfs";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_fabric>;
};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_mssio>;
};
&syscontroller {
microchip,bitstream-flash = <&sys_ctrl_flash>;
};

View File

@ -11,3 +11,22 @@ / {
"microchip,mpfs-icicle-kit",
"microchip,mpfs";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_fabric>;
};
/*
* Due to silicon errata, routing via MSS IOs doesn't work on ES devices.
* Instead, i2c1, appearing on B1/C1, which are normally MSS IOs, is routed
* via the fabric and back to B1/C1 via "fabric-test" functionality.
* This is done silently by Libero, so the iomux0 setting for i2c1 has to
* be fabric IO, despite tooling etc saying that MSS IOs are used.
*
* See Section 3.3 of https://ww1.microchip.com/downloads/aemDocuments/documents/FPGA/ProductDocuments/Errata/polarfiresoc/microsemi_polarfire_soc_fpga_egineering_samples_errata_er0219_v1.pdf
*/
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_fabric>;
};

View File

@ -135,29 +135,6 @@ &tdm_ext {
clock-frequency = <49152000>;
};
&camss {
assigned-clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>,
<&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>;
assigned-clock-rates = <49500000>, <198000000>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
};
port@1 {
reg = <1>;
camss_from_csi2rx: endpoint {
remote-endpoint = <&csi2rx_to_camss>;
};
};
};
};
&csi2rx {
assigned-clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>;
assigned-clock-rates = <297000000>;
@ -175,9 +152,7 @@ port@0 {
port@1 {
reg = <1>;
csi2rx_to_camss: endpoint {
remote-endpoint = <&camss_from_csi2rx>;
};
/* remote CAMSS endpoint */
};
};
};

View File

@ -1199,34 +1199,6 @@ csi_phy: phy@19820000 {
#phy-cells = <0>;
};
camss: isp@19840000 {
compatible = "starfive,jh7110-camss";
reg = <0x0 0x19840000 0x0 0x10000>,
<0x0 0x19870000 0x0 0x30000>;
reg-names = "syscon", "isp";
clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>,
<&ispcrg JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C>,
<&ispcrg JH7110_ISPCLK_DVP_INV>,
<&ispcrg JH7110_ISPCLK_VIN_P_AXI_WR>,
<&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>,
<&syscrg JH7110_SYSCLK_ISP_TOP_CORE>,
<&syscrg JH7110_SYSCLK_ISP_TOP_AXI>;
clock-names = "apb_func", "wrapper_clk_c", "dvp_inv",
"axiwr", "mipi_rx0_pxl", "ispcore_2x",
"isp_axi";
resets = <&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_P>,
<&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_C>,
<&ispcrg JH7110_ISPRST_VIN_P_AXI_RD>,
<&ispcrg JH7110_ISPRST_VIN_P_AXI_WR>,
<&syscrg JH7110_SYSRST_ISP_TOP>,
<&syscrg JH7110_SYSRST_ISP_TOP_AXI>;
reset-names = "wrapper_p", "wrapper_c", "axird",
"axiwr", "isp_top_n", "isp_top_axi";
power-domains = <&pwrc JH7110_PD_ISP>;
interrupts = <92>, <87>, <90>, <88>;
status = "disabled";
};
voutcrg: clock-controller@295c0000 {
compatible = "starfive,jh7110-voutcrg";
reg = <0x0 0x295c0000 0x0 0x10000>;

View File

@ -14,5 +14,6 @@ generic-y += ticket_spinlock.h
generic-y += qrwlock.h
generic-y += qrwlock_types.h
generic-y += qspinlock.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += vmlinux.lds.h

View File

@ -7,3 +7,4 @@ generated-y += unistd_nr.h
generic-y += asm-offsets.h
generic-y += mcs_spinlock.h
generic-y += mmzone.h
generic-y += ring_buffer.h

View File

@ -267,6 +267,7 @@ static int dat_split_ste(struct kvm_s390_mmu_cache *mc, union pmd *pmdp, gfn_t g
/* No need to take locks as the page table is not installed yet. */
pgste_init.prefix_notif = old.s.fc1.prefix_notif;
pgste_init.vsie_notif = old.s.fc1.vsie_notif;
pgste_init.vsie_gmem = old.s.fc1.vsie_notif;
pgste_init.pcl = uses_skeys && init.h.i;
dat_init_pgstes(pt, pgste_init.val);
} else {

View File

@ -145,7 +145,8 @@ union pgste {
unsigned long cmma_d : 1; /* Dirty flag for CMMA bits */
unsigned long prefix_notif : 1; /* Guest prefix invalidation notification */
unsigned long vsie_notif : 1; /* Referenced in a shadow table */
unsigned long : 5;
unsigned long vsie_gmem : 1; /* Contains nested guest memory */
unsigned long : 4;
unsigned long : 8;
};
struct {

View File

@ -1445,6 +1445,7 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union
} else {
pgste = _gmap_ptep_xchg(sg->parent, ptep_h, newpte, pgste, f->gfn, false);
pgste.vsie_notif = 1;
pgste.vsie_gmem = 1;
}
pgste_set_unlock(ptep_h, pgste);
if (rc)

View File

@ -125,7 +125,7 @@ struct gmap *gmap_new_child(struct gmap *parent, gfn_t limit)
int gmap_set_limit(struct gmap *gmap, gfn_t limit)
{
struct kvm_s390_mmu_cache *mc;
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
int rc, type;
type = gmap_limit_to_type(limit);
@ -142,7 +142,6 @@ int gmap_set_limit(struct gmap *gmap, gfn_t limit)
rc = dat_set_asce_limit(mc, &gmap->asce, type);
} while (rc == -ENOMEM);
kvm_s390_free_mmu_cache(mc);
return 0;
}
@ -822,8 +821,8 @@ int gmap_ucas_translate(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, gpa_t
int gmap_ucas_map(struct gmap *gmap, gfn_t p_gfn, gfn_t c_gfn, unsigned long count)
{
struct kvm_s390_mmu_cache *mc;
int rc;
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
int rc = 0;
mc = kvm_s390_new_mmu_cache();
if (!mc)
@ -1026,13 +1025,15 @@ int gmap_insert_rmap(struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, int level)
int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn,
kvm_pfn_t pfn, int level, bool wr)
{
unsigned long bitmask;
union crste *crstep;
union pgste pgste;
union pte *ptep;
union pte pte;
int flags, rc;
KVM_BUG_ON(!is_shadow(sg), sg->kvm);
if (KVM_BUG_ON(!is_shadow(sg) || level <= TABLE_TYPE_PAGE_TABLE, sg->kvm))
return -EINVAL;
lockdep_assert_held(&sg->parent->children_lock);
flags = DAT_WALK_SPLIT_ALLOC | (uses_skeys(sg->parent) ? DAT_WALK_USES_SKEYS : 0);
@ -1041,8 +1042,9 @@ int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gf
if (rc)
return rc;
if (level <= TABLE_TYPE_REGION1) {
bitmask = -1UL << (8 + 11 * level);
scoped_guard(spinlock, &sg->host_to_rmap_lock)
rc = gmap_insert_rmap(sg, p_gfn, r_gfn, level);
rc = gmap_insert_rmap(sg, p_gfn, r_gfn & bitmask, level);
}
if (rc)
return rc;
@ -1143,8 +1145,10 @@ void _gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn)
}
scoped_guard(spinlock, &sg->host_to_rmap_lock)
head = radix_tree_delete(&sg->host_to_rmap, gfn);
gmap_for_each_rmap_safe(rmap, rnext, head)
gmap_for_each_rmap_safe(rmap, rnext, head) {
gmap_unshadow_level(sg, rmap->r_gfn, rmap->level);
kfree(rmap);
}
}
}

View File

@ -167,6 +167,36 @@ static inline bool gmap_unmap_prefix(struct gmap *gmap, gfn_t gfn, gfn_t end)
return _gmap_unmap_prefix(gmap, gfn, end, false);
}
/**
* pte_needs_unshadow() -- Check if the pte operations triggers unshadowing.
* @oldpte: the previous value for the guest pte.
* @newpte: the new pte being set.
* @pgste: the pgste for the pte entry.
*
* If the pgste.vsie_notif bit is not set, return false: the page is not
* involved in vsie and thus should not trigger an unshadow operation.
*
* If the pgste.vsie_gmem bit is set, this pte represents shadowed guest
* memory. The access rights on g3's memory should be synchronized with g1's
* and g2's. Therefore unshadowing is triggered if the new and old pte
* differ in protection, or if the new pte is invalid.
*
* If the pgste.vsie_gmem bit is not set, this pte maps the g2 dat tables
* for g3. If the entry becomes writable or absent, it becomes impossible to
* guarantee that the shadow mapping will match g2's mapping. In that case,
* trigger an unshadow event.
*
* Return: true if an unshadow event should be triggered, otherwise false.
*/
static inline bool pte_needs_unshadow(union pte oldpte, union pte newpte, union pgste pgste)
{
if (!pgste.vsie_notif)
return false;
if (pgste.vsie_gmem)
return (oldpte.h.p != newpte.h.p) || newpte.h.i;
return !newpte.h.p || !newpte.s.pr;
}
static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, union pte newpte,
union pgste pgste, gfn_t gfn, bool needs_lock)
{
@ -180,8 +210,9 @@ static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, un
pgste.prefix_notif = 0;
gmap_unmap_prefix(gmap, gfn, gfn + 1);
}
if (pgste.vsie_notif && (ptep->h.p != newpte.h.p || newpte.h.i)) {
if (pte_needs_unshadow(*ptep, newpte, pgste)) {
pgste.vsie_notif = 0;
pgste.vsie_gmem = 0;
if (needs_lock)
gmap_handle_vsie_unshadow_event(gmap, gfn);
else
@ -189,6 +220,7 @@ static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, un
}
if (!ptep->s.d && newpte.s.d && !newpte.s.s)
SetPageDirty(pfn_to_page(newpte.h.pfra));
pgste.zero = 0;
return __dat_ptep_xchg(ptep, pgste, newpte, gfn, gmap->asce, uses_skeys(gmap));
}
@ -198,6 +230,30 @@ static inline union pgste gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, uni
return _gmap_ptep_xchg(gmap, ptep, newpte, pgste, gfn, true);
}
/**
* crste_needs_unshadow() -- Check if the crste operations triggers unshadowing.
* @oldcrste: the previous value for the crste.
* @newcrste: the new value for the crste.
*
* If the old crste did not have the vsie_notif bit set, return false: the
* page is not involved in vsie and thus should not trigger an unshadow
* operation. Conversely, if the bit is set, it can only be g3 memory, since
* dat tables are never mapped using large pages.
*
* Similar to the pgste.vsie_gmem case of pte_needs_unshadow(), if the
* protection bit is changing or the new page is invalid, trigger an
* unshadow event. Also trigger an unshadow event if the new crste does not
* have the vsie_notif bit set.
*
* Return: true if an unshadow event should be triggered, otherwise false.
*/
static inline bool crste_needs_unshadow(union crste oldcrste, union crste newcrste)
{
if (!oldcrste.s.fc1.vsie_notif)
return false;
return (newcrste.h.p != oldcrste.h.p) || newcrste.h.i || !newcrste.s.fc1.vsie_notif;
}
static inline bool __must_check _gmap_crstep_xchg_atomic(struct gmap *gmap, union crste *crstep,
union crste oldcrste, union crste newcrste,
gfn_t gfn, bool needs_lock)
@ -216,8 +272,7 @@ static inline bool __must_check _gmap_crstep_xchg_atomic(struct gmap *gmap, unio
newcrste.s.fc1.prefix_notif = 0;
gmap_unmap_prefix(gmap, gfn, gfn + align);
}
if (crste_leaf(oldcrste) && oldcrste.s.fc1.vsie_notif &&
(newcrste.h.p || newcrste.h.i || !newcrste.s.fc1.vsie_notif)) {
if (crste_leaf(oldcrste) && crste_needs_unshadow(oldcrste, newcrste)) {
newcrste.s.fc1.vsie_notif = 0;
if (needs_lock)
gmap_handle_vsie_unshadow_event(gmap, gfn);

View File

@ -3,4 +3,5 @@ generated-y += syscall_table.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += ring_buffer.h
generic-y += text-patching.h

View File

@ -4,4 +4,5 @@ generated-y += syscall_table_64.h
generic-y += agp.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += ring_buffer.h
generic-y += text-patching.h

View File

@ -17,6 +17,7 @@ generic-y += module.lds.h
generic-y += parport.h
generic-y += percpu.h
generic-y += preempt.h
generic-y += ring_buffer.h
generic-y += runtime-const.h
generic-y += softirq_stack.h
generic-y += switch_to.h

View File

@ -14,3 +14,4 @@ generic-y += early_ioremap.h
generic-y += fprobe.h
generic-y += mcs_spinlock.h
generic-y += mmzone.h
generic-y += ring_buffer.h

View File

@ -6,5 +6,6 @@ generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += qrwlock.h
generic-y += qspinlock.h
generic-y += ring_buffer.h
generic-y += user.h
generic-y += text-patching.h

View File

@ -134,27 +134,69 @@ EXPORT_SYMBOL(crypto_krb5_how_much_data);
* Find the offset and size of the data in a secure message so that this
* information can be used in the metadata buffer which will get added to the
* digest by crypto_krb5_verify_mic().
*
* Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if
* the mode is unsupported.
*/
void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len)
int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len)
{
switch (mode) {
case KRB5_CHECKSUM_MODE:
if (*_len < krb5->cksum_len)
return -EBADMSG;
*_offset += krb5->cksum_len;
*_len -= krb5->cksum_len;
return;
return 0;
case KRB5_ENCRYPT_MODE:
if (*_len < krb5->conf_len + krb5->cksum_len)
return -EBADMSG;
*_offset += krb5->conf_len;
*_len -= krb5->conf_len + krb5->cksum_len;
return;
return 0;
default:
WARN_ON_ONCE(1);
return;
return -EINVAL;
}
}
EXPORT_SYMBOL(crypto_krb5_where_is_the_data);
/**
* crypto_krb5_check_data_len - Check a message is big enough
* @krb5: The encoding to use.
* @mode: Mode of operation.
* @len: The length of the secure blob.
* @min_content: Minimum length of the content inside the blob.
*
* Check that a message is large enough to hold whatever bits the encryption
* type wants to glue on (nonce, checksum) plus a minimum amount of content.
*
* Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if
* the mode is unsupported.
*/
int crypto_krb5_check_data_len(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t len, size_t min_content)
{
switch (mode) {
case KRB5_CHECKSUM_MODE:
if (len < krb5->cksum_len ||
len - krb5->cksum_len < min_content)
return -EBADMSG;
return 0;
case KRB5_ENCRYPT_MODE:
if (len < krb5->conf_len + krb5->cksum_len ||
len - (krb5->conf_len + krb5->cksum_len) < min_content)
return -EBADMSG;
return 0;
default:
WARN_ON_ONCE(1);
return -EINVAL;
}
}
EXPORT_SYMBOL(crypto_krb5_check_data_len);
/*
* Prepare the encryption with derived key data.
*/

View File

@ -5584,6 +5584,7 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
link->pmp = pmp;
link->active_tag = ATA_TAG_POISON;
link->hw_sata_spd_limit = UINT_MAX;
INIT_WORK(&link->deferred_qc_work, ata_scsi_deferred_qc_work);
/* can't use iterator, ap isn't initialized yet */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
@ -5666,7 +5667,6 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
mutex_init(&ap->scsi_scan_mutex);
INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
INIT_DELAYED_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
INIT_WORK(&ap->deferred_qc_work, ata_scsi_deferred_qc_work);
INIT_LIST_HEAD(&ap->eh_done_q);
init_waitqueue_head(&ap->eh_wait_q);
init_completion(&ap->park_req_pending);
@ -6291,12 +6291,15 @@ static void ata_port_detach(struct ata_port *ap)
/* It better be dead now and not have any remaining deferred qc. */
WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED));
WARN_ON(ap->deferred_qc);
cancel_work_sync(&ap->deferred_qc_work);
cancel_delayed_work_sync(&ap->hotplug_task);
cancel_delayed_work_sync(&ap->scsi_rescan_task);
ata_for_each_link(link, ap, PMP_FIRST) {
WARN_ON(link->deferred_qc);
cancel_work_sync(&link->deferred_qc_work);
}
/* Delete port multiplier link transport devices */
if (ap->pmp_link) {
int i;

View File

@ -651,11 +651,11 @@ int ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
if (qc->scsicmd != scmd)
continue;
if ((qc->flags & ATA_QCFLAG_ACTIVE) ||
qc == ap->deferred_qc)
qc == qc->dev->link->deferred_qc)
break;
}
if (i < ATA_MAX_QUEUE && qc == ap->deferred_qc) {
if (i < ATA_MAX_QUEUE && qc == qc->dev->link->deferred_qc) {
/*
* This is a deferred command that timed out while
* waiting for the command queue to drain. Since the qc
@ -666,8 +666,8 @@ int ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
* deferred qc work from issuing this qc.
*/
WARN_ON_ONCE(qc->flags & ATA_QCFLAG_ACTIVE);
ap->deferred_qc = NULL;
cancel_work(&ap->deferred_qc_work);
qc->dev->link->deferred_qc = NULL;
cancel_work(&qc->dev->link->deferred_qc_work);
set_host_byte(scmd, DID_TIME_OUT);
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
} else if (i < ATA_MAX_QUEUE) {

View File

@ -110,13 +110,24 @@ int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc)
{
struct ata_link *link = qc->dev->link;
struct ata_port *ap = link->ap;
int ret;
if (ap->excl_link == NULL || ap->excl_link == link) {
if (ap->nr_active_links == 0 || ata_link_active(link)) {
qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
return ata_std_qc_defer(qc);
ret = ata_std_qc_defer(qc);
if (ret == ATA_DEFER_LINK)
return ATA_DEFER_LINK_EXCL;
return ret;
}
/*
* Note: ap->excl_link contains the link that is next in line,
* i.e. implicit round robin. If there is only one link
* dispatching, ap->excl_link will be left unclaimed, allowing
* other links to set ap->excl_link, ensuring that the currently
* active link cannot queue any more.
*/
ap->excl_link = link;
}
@ -571,8 +582,11 @@ static void sata_pmp_detach(struct ata_device *dev)
if (ap->ops->pmp_detach)
ap->ops->pmp_detach(ap);
ata_for_each_link(tlink, ap, EDGE)
ata_for_each_link(tlink, ap, EDGE) {
WARN_ON(tlink->deferred_qc);
cancel_work_sync(&tlink->deferred_qc_work);
ata_eh_detach_dev(tlink->device);
}
spin_lock_irqsave(ap->lock, flags);
ap->nr_pmp_links = 0;

View File

@ -1664,8 +1664,9 @@ static void ata_scsi_qc_done(struct ata_queued_cmd *qc, bool set_result,
void ata_scsi_deferred_qc_work(struct work_struct *work)
{
struct ata_port *ap =
container_of(work, struct ata_port, deferred_qc_work);
struct ata_link *link =
container_of(work, struct ata_link, deferred_qc_work);
struct ata_port *ap = link->ap;
struct ata_queued_cmd *qc;
unsigned long flags;
@ -1676,10 +1677,10 @@ void ata_scsi_deferred_qc_work(struct work_struct *work)
* such case, we should not need any more deferring the qc, so warn if
* qc_defer() says otherwise.
*/
qc = ap->deferred_qc;
qc = link->deferred_qc;
if (qc && !ata_port_eh_scheduled(ap)) {
WARN_ON_ONCE(ap->ops->qc_defer(qc));
ap->deferred_qc = NULL;
link->deferred_qc = NULL;
ata_qc_issue(qc);
}
@ -1688,7 +1689,7 @@ void ata_scsi_deferred_qc_work(struct work_struct *work)
void ata_scsi_requeue_deferred_qc(struct ata_port *ap)
{
struct ata_queued_cmd *qc = ap->deferred_qc;
struct ata_link *link;
lockdep_assert_held(ap->lock);
@ -1697,16 +1698,21 @@ void ata_scsi_requeue_deferred_qc(struct ata_port *ap)
* do not try to be smart about what to do with this deferred command
* and simply requeue it by completing it with DID_REQUEUE.
*/
if (qc) {
ap->deferred_qc = NULL;
cancel_work(&ap->deferred_qc_work);
ata_scsi_qc_done(qc, true, DID_REQUEUE << 16);
ata_for_each_link(link, ap, PMP_FIRST) {
struct ata_queued_cmd *qc = link->deferred_qc;
if (qc) {
link->deferred_qc = NULL;
cancel_work(&link->deferred_qc_work);
ata_scsi_qc_done(qc, true, DID_REQUEUE << 16);
}
}
}
static void ata_scsi_schedule_deferred_qc(struct ata_port *ap)
static void ata_scsi_schedule_deferred_qc(struct ata_link *link)
{
struct ata_queued_cmd *qc = ap->deferred_qc;
struct ata_queued_cmd *qc = link->deferred_qc;
struct ata_port *ap = link->ap;
lockdep_assert_held(ap->lock);
@ -1723,12 +1729,12 @@ static void ata_scsi_schedule_deferred_qc(struct ata_port *ap)
return;
}
if (!ap->ops->qc_defer(qc))
queue_work(system_highpri_wq, &ap->deferred_qc_work);
queue_work(system_highpri_wq, &link->deferred_qc_work);
}
static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_link *link = qc->dev->link;
struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd;
bool have_sense = qc->flags & ATA_QCFLAG_SENSE_VALID;
@ -1759,22 +1765,23 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
ata_scsi_qc_done(qc, false, 0);
ata_scsi_schedule_deferred_qc(ap);
ata_scsi_schedule_deferred_qc(link);
}
static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *qc)
{
struct ata_link *link = qc->dev->link;
int ret;
if (!ap->ops->qc_defer)
goto issue;
goto issue_qc;
/*
* If we already have a deferred qc, then rely on the SCSI layer to
* requeue and defer all incoming commands until the deferred qc is
* processed, once all on-going commands complete.
*/
if (ap->deferred_qc) {
if (link->deferred_qc) {
ata_qc_free(qc);
return SCSI_MLQUEUE_DEVICE_BUSY;
}
@ -1786,38 +1793,46 @@ static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *qc)
break;
case ATA_DEFER_LINK:
ret = SCSI_MLQUEUE_DEVICE_BUSY;
break;
goto defer_qc;
case ATA_DEFER_LINK_EXCL:
/*
* Drivers making use of ap->excl_link cannot store the QC in
* link->deferred_qc, because the ap->excl_link handling is
* incompatible with the link->deferred_qc workqueue handling.
*/
ret = SCSI_MLQUEUE_DEVICE_BUSY;
goto free_qc;
case ATA_DEFER_PORT:
ret = SCSI_MLQUEUE_HOST_BUSY;
break;
goto free_qc;
default:
WARN_ON_ONCE(1);
ret = SCSI_MLQUEUE_HOST_BUSY;
break;
goto free_qc;
}
if (ret) {
/*
* We must defer this qc: if this is not an NCQ command, keep
* this qc as a deferred one and report to the SCSI layer that
* we issued it so that it is not requeued. The deferred qc will
* be issued with the port deferred_qc_work once all on-going
* commands complete.
*/
if (!ata_is_ncq(qc->tf.protocol)) {
ap->deferred_qc = qc;
return 0;
}
/* Force a requeue of the command to defer its execution. */
ata_qc_free(qc);
return ret;
}
issue:
issue_qc:
ata_qc_issue(qc);
return 0;
defer_qc:
/*
* We must defer this qc: if this is not an NCQ command, keep
* this qc as a deferred one and report to the SCSI layer that
* we issued it so that it is not requeued. The deferred qc will
* be issued with the port deferred_qc_work once all on-going
* commands complete.
*/
if (!ata_is_ncq(qc->tf.protocol)) {
link->deferred_qc = qc;
return 0;
}
free_qc:
/* Force a requeue of the command to defer its execution. */
ata_qc_free(qc);
return ret;
}
/**

View File

@ -789,6 +789,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
struct ata_link *link = qc->dev->link;
struct ata_port *ap = link->ap;
u8 prot = qc->tf.protocol;
int ret;
/*
* There is a bug in the chip:
@ -826,7 +827,10 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
}
return ata_std_qc_defer(qc);
ret = ata_std_qc_defer(qc);
if (ret == ATA_DEFER_LINK)
return ATA_DEFER_LINK_EXCL;
return ret;
}
static enum ata_completion_errors sil24_qc_prep(struct ata_queued_cmd *qc)

View File

@ -1230,8 +1230,10 @@ void memblk_nr_poison_inc(unsigned long pfn)
const unsigned long block_id = pfn_to_block_id(pfn);
struct memory_block *mem = find_memory_block_by_id(block_id);
if (mem)
if (mem) {
atomic_long_inc(&mem->nr_hwpoison);
put_device(&mem->dev);
}
}
void memblk_nr_poison_sub(unsigned long pfn, long i)
@ -1239,8 +1241,10 @@ void memblk_nr_poison_sub(unsigned long pfn, long i)
const unsigned long block_id = pfn_to_block_id(pfn);
struct memory_block *mem = find_memory_block_by_id(block_id);
if (mem)
if (mem) {
atomic_long_sub(i, &mem->nr_hwpoison);
put_device(&mem->dev);
}
}
static unsigned long memblk_nr_poison(struct memory_block *mem)

View File

@ -4565,24 +4565,12 @@ static int rbd_register_watch(struct rbd_device *rbd_dev)
return ret;
}
static void cancel_tasks_sync(struct rbd_device *rbd_dev)
{
dout("%s rbd_dev %p\n", __func__, rbd_dev);
cancel_work_sync(&rbd_dev->acquired_lock_work);
cancel_work_sync(&rbd_dev->released_lock_work);
cancel_delayed_work_sync(&rbd_dev->lock_dwork);
cancel_work_sync(&rbd_dev->unlock_work);
}
/*
* header_rwsem must not be held to avoid a deadlock with
* rbd_dev_refresh() when flushing notifies.
*/
static void rbd_unregister_watch(struct rbd_device *rbd_dev)
{
cancel_tasks_sync(rbd_dev);
mutex_lock(&rbd_dev->watch_mutex);
if (rbd_dev->watch_state == RBD_WATCH_STATE_REGISTERED)
__rbd_unregister_watch(rbd_dev);
@ -6548,10 +6536,18 @@ static int rbd_add_parse_args(const char *buf,
static void rbd_dev_image_unlock(struct rbd_device *rbd_dev)
{
dout("%s rbd_dev %p\n", __func__, rbd_dev);
disable_delayed_work_sync(&rbd_dev->lock_dwork);
disable_work_sync(&rbd_dev->unlock_work);
down_write(&rbd_dev->lock_rwsem);
if (__rbd_is_lock_owner(rbd_dev))
__rbd_release_lock(rbd_dev);
up_write(&rbd_dev->lock_rwsem);
flush_work(&rbd_dev->acquired_lock_work);
flush_work(&rbd_dev->released_lock_work);
}
/*

View File

@ -582,12 +582,10 @@ static int btintel_pcie_get_mac_access(struct btintel_pcie_data *data)
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS;
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ;
if ((reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS) == 0)
if (!(reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ)) {
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ;
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
}
do {
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
@ -607,16 +605,10 @@ static void btintel_pcie_release_mac_access(struct btintel_pcie_data *data)
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ)
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ) {
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ;
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS)
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS;
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ)
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ;
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
}
}
static void *btintel_pcie_copy_tlv(void *dest, enum btintel_pcie_tlv_type type,

View File

@ -34,9 +34,6 @@
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS (BIT(20))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ (BIT(21))
/* Stop MAC Access disconnection request */
#define BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS (BIT(22))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ (BIT(23))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_STS (BIT(28))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON (BIT(29))

View File

@ -537,6 +537,7 @@ static void btmtk_usb_wmt_recv(struct urb *urb)
return;
} else if (urb->status == -ENOENT) {
/* Avoid suspend failed when usb_kill_urb */
kfree(urb->setup_packet);
return;
}
@ -610,6 +611,7 @@ static int btmtk_usb_submit_wmt_recv_urb(struct hci_dev *hdev)
if (err != -EPERM && err != -ENODEV)
bt_dev_err(hdev, "urb %p submission failed (%d)",
urb, -err);
kfree(dr);
usb_unanchor_urb(urb);
}
@ -719,8 +721,8 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
case BTMTK_WMT_FUNC_CTRL:
if (!skb_pull_data(data->evt_skb,
sizeof(wmt_evt_funcc->status))) {
err = -EINVAL;
goto err_free_skb;
status = BTMTK_WMT_ON_UNDONE;
break;
}
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;

View File

@ -194,7 +194,15 @@ void hci_uart_init_work(struct work_struct *work)
err = hci_register_dev(hu->hdev);
if (err < 0) {
BT_ERR("Can't register HCI device");
percpu_down_write(&hu->proto_lock);
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
percpu_up_write(&hu->proto_lock);
/* Safely cancel work after clearing flags */
cancel_work_sync(&hu->write_work);
/* Close protocol before freeing hdev */
hu->proto->close(hu);
hdev = hu->hdev;
hu->hdev = NULL;
@ -263,8 +271,12 @@ static int hci_uart_open(struct hci_dev *hdev)
/* Close device */
static int hci_uart_close(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
BT_DBG("hdev %p", hdev);
cancel_work_sync(&hu->write_work);
hci_uart_flush(hdev);
hdev->flush = NULL;
return 0;
@ -531,6 +543,7 @@ static void hci_uart_tty_close(struct tty_struct *tty)
{
struct hci_uart *hu = tty->disc_data;
struct hci_dev *hdev;
bool proto_ready;
BT_DBG("tty %p", tty);
@ -540,24 +553,38 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (!hu)
return;
hdev = hu->hdev;
if (hdev)
hci_uart_close(hdev);
/* Wait for init_ready to finish to prevent registration races */
cancel_work_sync(&hu->init_ready);
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
proto_ready = test_bit(HCI_UART_PROTO_READY, &hu->flags);
if (proto_ready) {
percpu_down_write(&hu->proto_lock);
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
percpu_up_write(&hu->proto_lock);
}
cancel_work_sync(&hu->init_ready);
cancel_work_sync(&hu->write_work);
/*
* Unconditionally cancel write_work AFTER clearing PROTO_READY.
* This ensures that concurrent protocol timers cannot requeue
* write_work via hci_uart_tx_wakeup(), permanently preventing
* double-free races and UAFs.
*/
cancel_work_sync(&hu->write_work);
hdev = hu->hdev;
if (hdev)
hci_uart_close(hdev); /* proto->flush is safely skipped */
if (proto_ready) {
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
/* Close protocol before freeing hdev (intrinsically purges queues) */
hu->proto->close(hu);
if (hdev)
hci_free_dev(hdev);
}
clear_bit(HCI_UART_PROTO_SET, &hu->flags);
@ -625,11 +652,12 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
* tty caller
*/
hu->proto->recv(hu, data, count);
percpu_up_read(&hu->proto_lock);
if (hu->hdev)
hu->hdev->stat.byte_rx += count;
percpu_up_read(&hu->proto_lock);
tty_unthrottle(tty);
}
@ -695,6 +723,10 @@ static int hci_uart_register_dev(struct hci_uart *hu)
percpu_down_write(&hu->proto_lock);
clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
percpu_up_write(&hu->proto_lock);
/* Cancel work after clearing flags */
cancel_work_sync(&hu->write_work);
/* Close protocol before freeing hdev */
hu->proto->close(hu);
hu->hdev = NULL;
hci_free_dev(hdev);

View File

@ -48,13 +48,12 @@
#define HCI_MAX_IBS_SIZE 10
#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
#define IBS_BTSOC_TX_IDLE_TIMEOUT_MS 200
#define IBS_BTSOC_TX_IDLE_TIMEOUT msecs_to_jiffies(200)
#define IBS_HOST_TX_IDLE_TIMEOUT_MS 2000
#define CMD_TRANS_TIMEOUT_MS 100
#define MEMDUMP_TIMEOUT_MS 8000
#define IBS_DISABLE_SSR_TIMEOUT_MS \
(MEMDUMP_TIMEOUT_MS + FW_DOWNLOAD_TIMEOUT_MS)
#define FW_DOWNLOAD_TIMEOUT_MS 3000
#define CMD_TRANS_TIMEOUT msecs_to_jiffies(100)
#define MEMDUMP_TIMEOUT msecs_to_jiffies(8000)
#define FW_DOWNLOAD_TIMEOUT msecs_to_jiffies(3000)
#define IBS_DISABLE_SSR_TIMEOUT (MEMDUMP_TIMEOUT + FW_DOWNLOAD_TIMEOUT)
/* susclk rate */
#define SUSCLK_RATE_32KHZ 32768
@ -1096,7 +1095,7 @@ static void qca_controller_memdump(struct work_struct *work)
queue_delayed_work(qca->workqueue,
&qca->ctrl_memdump_timeout,
msecs_to_jiffies(MEMDUMP_TIMEOUT_MS));
MEMDUMP_TIMEOUT);
skb_pull(skb, sizeof(qca_memdump->ram_dump_size));
qca_memdump->current_seq_no = 0;
qca_memdump->received_dump = 0;
@ -1369,7 +1368,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
if (hu->serdev)
serdev_device_wait_until_sent(hu->serdev,
msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
CMD_TRANS_TIMEOUT);
/* Give the controller time to process the request */
switch (qca_soc_type(hu)) {
@ -1401,8 +1400,8 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed)
static int qca_send_power_pulse(struct hci_uart *hu, bool on)
{
int timeout = CMD_TRANS_TIMEOUT;
int ret;
int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE;
/* These power pulses are single byte command which are sent
@ -1607,7 +1606,7 @@ static void qca_wait_for_dump_collection(struct hci_dev *hdev)
struct qca_data *qca = hu->priv;
wait_on_bit_timeout(&qca->flags, QCA_MEMDUMP_COLLECTION,
TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT_MS);
TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT);
clear_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
}
@ -2591,7 +2590,7 @@ static void qca_serdev_remove(struct serdev_device *serdev)
static void qca_serdev_shutdown(struct serdev_device *serdev)
{
int ret;
int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
int timeout = CMD_TRANS_TIMEOUT;
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
struct hci_uart *hu = &qcadev->serdev_hu;
struct hci_dev *hdev = hu->hdev;
@ -2648,7 +2647,7 @@ static int __maybe_unused qca_suspend(struct device *dev)
bool tx_pending = false;
int ret = 0;
u8 cmd;
u32 wait_timeout = 0;
unsigned long wait_timeout = 0;
set_bit(QCA_SUSPENDING, &qca->flags);
@ -2669,15 +2668,15 @@ static int __maybe_unused qca_suspend(struct device *dev)
if (test_bit(QCA_IBS_DISABLED, &qca->flags) ||
test_bit(QCA_SSR_TRIGGERED, &qca->flags)) {
wait_timeout = test_bit(QCA_SSR_TRIGGERED, &qca->flags) ?
IBS_DISABLE_SSR_TIMEOUT_MS :
FW_DOWNLOAD_TIMEOUT_MS;
IBS_DISABLE_SSR_TIMEOUT :
FW_DOWNLOAD_TIMEOUT;
/* QCA_IBS_DISABLED flag is set to true, During FW download
* and during memory dump collection. It is reset to false,
* After FW download complete.
*/
wait_on_bit_timeout(&qca->flags, QCA_IBS_DISABLED,
TASK_UNINTERRUPTIBLE, msecs_to_jiffies(wait_timeout));
TASK_UNINTERRUPTIBLE, wait_timeout);
if (test_bit(QCA_IBS_DISABLED, &qca->flags)) {
bt_dev_err(hu->hdev, "SSR or FW download time out");
@ -2729,7 +2728,7 @@ static int __maybe_unused qca_suspend(struct device *dev)
if (tx_pending) {
serdev_device_wait_until_sent(hu->serdev,
msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
CMD_TRANS_TIMEOUT);
serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
}
@ -2738,7 +2737,7 @@ static int __maybe_unused qca_suspend(struct device *dev)
*/
ret = wait_event_interruptible_timeout(qca->suspend_wait_q,
qca->rx_ibs_state == HCI_IBS_RX_ASLEEP,
msecs_to_jiffies(IBS_BTSOC_TX_IDLE_TIMEOUT_MS));
IBS_BTSOC_TX_IDLE_TIMEOUT);
if (ret == 0) {
ret = -ETIMEDOUT;
goto error;

View File

@ -1394,8 +1394,8 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
err_register:
dpll_pin_put(pin->dpll_pin, &pin->tracker);
pin->dpll_pin = NULL;
err_pin_get:
pin->dpll_pin = NULL;
fwnode_handle_put(pin->fwnode);
pin->fwnode = NULL;
zl3073x_pin_props_put(props);
@ -1563,8 +1563,10 @@ zl3073x_dpll_pins_register(struct zl3073x_dpll *zldpll)
}
rc = zl3073x_dpll_pin_register(pin, index);
if (rc)
if (rc) {
zl3073x_dpll_pin_free(pin);
goto error;
}
list_add(&pin->list, &zldpll->pins);
}

View File

@ -26,6 +26,8 @@ static int ffa_device_match(struct device *dev, const struct device_driver *drv)
id_table = to_ffa_driver(drv)->id_table;
ffa_dev = to_ffa_dev(dev);
if (!id_table)
return 0;
while (!uuid_is_null(&id_table->uuid)) {
/*
@ -123,7 +125,7 @@ int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
{
int ret;
if (!driver->probe)
if (!driver->probe || !driver->id_table)
return -EINVAL;
driver->driver.bus = &ffa_bus_type;

View File

@ -87,6 +87,7 @@ static inline int ffa_to_linux_errno(int errno)
struct ffa_pcpu_irq {
struct ffa_drv_info *info;
struct work_struct notif_pcpu_work;
};
struct ffa_drv_info {
@ -100,13 +101,13 @@ struct ffa_drv_info {
bool mem_ops_native;
bool msg_direct_req2_supp;
bool bitmap_created;
bool bus_notifier_registered;
bool notif_enabled;
unsigned int sched_recv_irq;
unsigned int notif_pend_irq;
unsigned int cpuhp_state;
struct ffa_pcpu_irq __percpu *irq_pcpu;
struct workqueue_struct *notif_pcpu_wq;
struct work_struct notif_pcpu_work;
struct work_struct sched_recv_irq_work;
struct xarray partition_info;
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
@ -322,6 +323,12 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
#define PART_INFO_ID_MASK GENMASK(15, 0)
#define PART_INFO_EXEC_CXT_MASK GENMASK(31, 16)
#define PART_INFO_PROPS_MASK GENMASK(63, 32)
#define FFA_PART_INFO_GET_REGS_FIRST_REG 3
#define FFA_PART_INFO_GET_REGS_REGS_PER_DESC 3
#define FFA_PART_INFO_GET_REGS_MAX_DESC \
(((sizeof(ffa_value_t) / sizeof_field(ffa_value_t, a0)) - \
FFA_PART_INFO_GET_REGS_FIRST_REG) / \
FFA_PART_INFO_GET_REGS_REGS_PER_DESC)
#define PART_INFO_ID(x) ((u16)(FIELD_GET(PART_INFO_ID_MASK, (x))))
#define PART_INFO_EXEC_CXT(x) ((u16)(FIELD_GET(PART_INFO_EXEC_CXT_MASK, (x))))
#define PART_INFO_PROPERTIES(x) ((u32)(FIELD_GET(PART_INFO_PROPS_MASK, (x))))
@ -329,15 +336,13 @@ static int
__ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
struct ffa_partition_info *buffer, int num_parts)
{
u16 buf_sz, start_idx, cur_idx, count = 0, prev_idx = 0, tag = 0;
u16 buf_sz, start_idx = 0, cur_idx, count = 0, tag = 0;
struct ffa_partition_info *buf = buffer;
ffa_value_t partition_info;
do {
__le64 *regs;
int idx;
start_idx = prev_idx ? prev_idx + 1 : 0;
int idx, nr_desc, buf_idx;
invoke_ffa_fn((ffa_value_t){
.a0 = FFA_PARTITION_INFO_GET_REGS,
@ -353,15 +358,28 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
count = PARTITION_COUNT(partition_info.a2);
if (!buffer || !num_parts) /* count only */
return count;
if (count > num_parts)
return -EINVAL;
cur_idx = CURRENT_INDEX(partition_info.a2);
if (cur_idx < start_idx || cur_idx >= count)
return -EINVAL;
nr_desc = cur_idx - start_idx + 1;
if (nr_desc > FFA_PART_INFO_GET_REGS_MAX_DESC)
return -EINVAL;
buf_idx = buf - buffer;
if (buf_idx + nr_desc > num_parts)
return -EINVAL;
tag = UUID_INFO_TAG(partition_info.a2);
buf_sz = PARTITION_INFO_SZ(partition_info.a2);
if (buf_sz > sizeof(*buffer))
buf_sz = sizeof(*buffer);
regs = (void *)&partition_info.a3;
for (idx = 0; idx < cur_idx - start_idx + 1; idx++, buf++) {
for (idx = 0; idx < nr_desc; idx++, buf++) {
union {
uuid_t uuid;
u64 regs[2];
@ -379,7 +397,7 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
uuid_copy(&buf->uuid, &uuid_regs.uuid);
regs += 3;
}
prev_idx = cur_idx;
start_idx = cur_idx + 1;
} while (cur_idx < (count - 1));
@ -1189,7 +1207,7 @@ static int
ffa_sched_recv_cb_update(struct ffa_device *dev, ffa_sched_recv_cb callback,
void *cb_data, bool is_registration)
{
struct ffa_dev_part_info *partition = NULL, *tmp;
struct ffa_dev_part_info *partition = NULL;
struct list_head *phead;
bool cb_valid;
@ -1202,11 +1220,11 @@ ffa_sched_recv_cb_update(struct ffa_device *dev, ffa_sched_recv_cb callback,
return -EINVAL;
}
list_for_each_entry_safe(partition, tmp, phead, node)
list_for_each_entry(partition, phead, node)
if (partition->dev == dev)
break;
if (!partition) {
if (&partition->node == phead) {
pr_err("%s: No such partition ID 0x%x\n", __func__, dev->vm_id);
return -EINVAL;
}
@ -1445,20 +1463,25 @@ static int ffa_notify_send(struct ffa_device *dev, int notify_id,
static void handle_notif_callbacks(u64 bitmap, enum notify_type type)
{
ffa_notifier_cb cb;
void *cb_data;
int notify_id;
struct notifier_cb_info *cb_info = NULL;
for (notify_id = 0; notify_id <= FFA_MAX_NOTIFICATIONS && bitmap;
notify_id++, bitmap >>= 1) {
if (!(bitmap & 1))
continue;
read_lock(&drv_info->notify_lock);
cb_info = notifier_hnode_get_by_type(notify_id, type);
read_unlock(&drv_info->notify_lock);
scoped_guard(read_lock, &drv_info->notify_lock) {
struct notifier_cb_info *cb_info;
if (cb_info && cb_info->cb)
cb_info->cb(notify_id, cb_info->cb_data);
cb_info = notifier_hnode_get_by_type(notify_id, type);
cb = cb_info ? cb_info->cb : NULL;
cb_data = cb_info ? cb_info->cb_data : NULL;
}
if (cb)
cb(notify_id, cb_data);
}
}
@ -1466,39 +1489,56 @@ static void handle_fwk_notif_callbacks(u32 bitmap)
{
void *buf;
uuid_t uuid;
void *fwk_cb_data;
int notify_id = 0, target;
ffa_fwk_notifier_cb fwk_cb;
struct ffa_indirect_msg_hdr *msg;
struct notifier_cb_info *cb_info = NULL;
size_t min_offset = offsetof(struct ffa_indirect_msg_hdr, uuid);
/* Only one framework notification defined and supported for now */
if (!(bitmap & FRAMEWORK_NOTIFY_RX_BUFFER_FULL))
return;
mutex_lock(&drv_info->rx_lock);
scoped_guard(mutex, &drv_info->rx_lock) {
u32 offset, size;
msg = drv_info->rx_buffer;
buf = kmemdup((void *)msg + msg->offset, msg->size, GFP_KERNEL);
if (!buf) {
mutex_unlock(&drv_info->rx_lock);
return;
msg = drv_info->rx_buffer;
offset = msg->offset;
size = msg->size;
if (!size || (offset != min_offset && offset < sizeof(*msg)) ||
offset > drv_info->rxtx_bufsz ||
size > drv_info->rxtx_bufsz - offset) {
pr_err("invalid framework notification message\n");
ffa_rx_release();
return;
}
buf = kmemdup((void *)msg + offset, size, GFP_KERNEL);
if (!buf) {
ffa_rx_release();
return;
}
target = SENDER_ID(msg->send_recv_id);
if (offset >= sizeof(*msg))
uuid_copy(&uuid, &msg->uuid);
else
uuid_copy(&uuid, &uuid_null);
ffa_rx_release();
}
target = SENDER_ID(msg->send_recv_id);
if (msg->offset >= sizeof(*msg))
uuid_copy(&uuid, &msg->uuid);
else
uuid_copy(&uuid, &uuid_null);
scoped_guard(read_lock, &drv_info->notify_lock) {
struct notifier_cb_info *cb_info;
mutex_unlock(&drv_info->rx_lock);
cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target,
&uuid);
fwk_cb = cb_info ? cb_info->fwk_cb : NULL;
fwk_cb_data = cb_info ? cb_info->cb_data : NULL;
}
ffa_rx_release();
read_lock(&drv_info->notify_lock);
cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target, &uuid);
read_unlock(&drv_info->notify_lock);
if (cb_info && cb_info->fwk_cb)
cb_info->fwk_cb(notify_id, cb_info->cb_data, buf);
if (fwk_cb)
fwk_cb(notify_id, fwk_cb_data, buf);
kfree(buf);
}
@ -1539,10 +1579,11 @@ ffa_self_notif_handle(u16 vcpu, bool is_per_vcpu, void *cb_data)
static void notif_pcpu_irq_work_fn(struct work_struct *work)
{
struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
struct ffa_pcpu_irq *pcpu = container_of(work, struct ffa_pcpu_irq,
notif_pcpu_work);
struct ffa_drv_info *info = pcpu->info;
ffa_self_notif_handle(smp_processor_id(), true, info);
notif_get_and_handle(info);
}
static const struct ffa_info_ops ffa_drv_info_ops = {
@ -1629,6 +1670,15 @@ static struct notifier_block ffa_bus_nb = {
.notifier_call = ffa_bus_notifier,
};
static void ffa_bus_notifier_unregister(void)
{
if (!drv_info->bus_notifier_registered)
return;
bus_unregister_notifier(&ffa_bus_type, &ffa_bus_nb);
drv_info->bus_notifier_registered = false;
}
static int ffa_xa_add_partition_info(struct ffa_device *dev)
{
struct ffa_dev_part_info *info;
@ -1712,6 +1762,8 @@ static void ffa_partitions_cleanup(void)
struct list_head *phead;
unsigned long idx;
ffa_bus_notifier_unregister();
/* Clean up/free all registered devices */
ffa_devices_unregister();
@ -1739,11 +1791,14 @@ static int ffa_setup_partitions(void)
ret = bus_register_notifier(&ffa_bus_type, &ffa_bus_nb);
if (ret)
pr_err("Failed to register FF-A bus notifiers\n");
else
drv_info->bus_notifier_registered = true;
}
count = ffa_partition_probe(&uuid_null, &pbuf);
if (count <= 0) {
pr_info("%s: No partitions found, error %d\n", __func__, count);
ffa_bus_notifier_unregister();
return -EINVAL;
}
@ -1811,7 +1866,7 @@ static irqreturn_t notif_pend_irq_handler(int irq, void *irq_data)
struct ffa_drv_info *info = pcpu->info;
queue_work_on(smp_processor_id(), info->notif_pcpu_wq,
&info->notif_pcpu_work);
&pcpu->notif_pcpu_work);
return IRQ_HANDLED;
}
@ -1928,8 +1983,11 @@ static int ffa_init_pcpu_irq(void)
if (!irq_pcpu)
return -ENOMEM;
for_each_present_cpu(cpu)
for_each_present_cpu(cpu) {
per_cpu_ptr(irq_pcpu, cpu)->info = drv_info;
INIT_WORK(&per_cpu_ptr(irq_pcpu, cpu)->notif_pcpu_work,
notif_pcpu_irq_work_fn);
}
drv_info->irq_pcpu = irq_pcpu;
@ -1958,7 +2016,6 @@ static int ffa_init_pcpu_irq(void)
}
INIT_WORK(&drv_info->sched_recv_irq_work, ffa_sched_recv_irq_work_fn);
INIT_WORK(&drv_info->notif_pcpu_work, notif_pcpu_irq_work_fn);
drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
if (!drv_info->notif_pcpu_wq)
return -EINVAL;
@ -2063,11 +2120,12 @@ static int __init ffa_init(void)
rxtx_bufsz = SZ_4K;
}
rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz);
drv_info->rxtx_bufsz = rxtx_bufsz;
drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
if (!drv_info->rx_buffer) {
ret = -ENOMEM;
goto free_pages;
goto free_drv_info;
}
drv_info->tx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
@ -2078,7 +2136,7 @@ static int __init ffa_init(void)
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
virt_to_phys(drv_info->rx_buffer),
PAGE_ALIGN(rxtx_bufsz) / FFA_PAGE_SIZE);
rxtx_bufsz / FFA_PAGE_SIZE);
if (ret) {
pr_err("failed to register FFA RxTx buffers\n");
goto free_pages;

View File

@ -402,21 +402,11 @@ static void __init efi_debugfs_init(void)
static inline void efi_debugfs_init(void) {}
#endif
/*
* We register the efi subsystem with the firmware subsystem and the
* efivars subsystem with the efi subsystem, if the system was booted with
* EFI.
*/
static int __init efisubsys_init(void)
static int __init efipostcore_init(void)
{
int error;
if (!efi_enabled(EFI_RUNTIME_SERVICES))
efi.runtime_supported_mask = 0;
if (!efi_enabled(EFI_BOOT))
return 0;
if (efi.runtime_supported_mask) {
/*
* Since we process only one efi_runtime_service() at a time, an
@ -428,9 +418,23 @@ static int __init efisubsys_init(void)
pr_err("Creating efi_rts_wq failed, EFI runtime services disabled.\n");
clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
efi.runtime_supported_mask = 0;
return 0;
}
}
return 0;
}
postcore_initcall(efipostcore_init);
/*
* We register the efi subsystem with the firmware subsystem and the
* efivars subsystem with the efi subsystem, if the system was booted with
* EFI.
*/
static int __init efisubsys_init(void)
{
int error;
if (!efi_enabled(EFI_BOOT))
return 0;
if (efi_rt_services_supported(EFI_RT_SUPPORTED_TIME_SERVICES))
platform_device_register_simple("rtc-efi", 0, NULL, 0);

View File

@ -311,11 +311,14 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
.callback = efifb_swap_width_height,
},
{
/* Lenovo IdeaPad Duet 3 10IGL5 with 1200x1920 portrait screen */
/*
* Lenovo IdeaPad Duet 3 10IGL5 and 10IGL5-LTE with
* 1200x1920 portrait screen
*/
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
"IdeaPad Duet 3 10IGL5"),
/* Non exact match to also match the LTE version */
DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"),
},
.callback = efifb_swap_width_height,
},

View File

@ -539,12 +539,22 @@ static int psci_system_suspend(unsigned long unused)
static int psci_system_suspend_enter(suspend_state_t state)
{
pm_set_resume_via_firmware();
return cpu_suspend(0, psci_system_suspend);
}
static int psci_system_suspend_begin(suspend_state_t state)
{
pm_set_suspend_via_firmware();
return 0;
}
static const struct platform_suspend_ops psci_suspend_ops = {
.valid = suspend_valid_only_mem,
.enter = psci_system_suspend_enter,
.begin = psci_system_suspend_begin,
};
static void __init psci_init_system_reset2(void)

View File

@ -2050,7 +2050,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
return 0;
if (unlikely(bsize < csize)) {
hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %zu)\n",
report->id, csize, bsize);
return -EINVAL;
}
@ -2072,7 +2072,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
rsize = max_buffer_size;
if (bsize < rsize) {
hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %zu)\n",
report->id, rsize, bsize);
return -EINVAL;
}

View File

@ -1297,7 +1297,9 @@ static int ipoib_hard_header(struct sk_buff *skb,
return IPOIB_HARD_LEN;
}
static void ipoib_set_mcast_list(struct net_device *dev)
static void ipoib_set_rx_mode_async(struct net_device *dev,
struct netdev_hw_addr_list *uc,
struct netdev_hw_addr_list *mc)
{
struct ipoib_dev_priv *priv = ipoib_priv(dev);
@ -2160,7 +2162,7 @@ static const struct net_device_ops ipoib_netdev_ops_pf = {
.ndo_fix_features = ipoib_fix_features,
.ndo_start_xmit = ipoib_start_xmit,
.ndo_tx_timeout = ipoib_timeout,
.ndo_set_rx_mode = ipoib_set_mcast_list,
.ndo_set_rx_mode_async = ipoib_set_rx_mode_async,
.ndo_get_iflink = ipoib_get_iflink,
.ndo_set_vf_link_state = ipoib_set_vf_link_state,
.ndo_get_vf_config = ipoib_get_vf_config,
@ -2183,7 +2185,7 @@ static const struct net_device_ops ipoib_netdev_ops_vf = {
.ndo_fix_features = ipoib_fix_features,
.ndo_start_xmit = ipoib_start_xmit,
.ndo_tx_timeout = ipoib_timeout,
.ndo_set_rx_mode = ipoib_set_mcast_list,
.ndo_set_rx_mode_async = ipoib_set_rx_mode_async,
.ndo_get_iflink = ipoib_get_iflink,
.ndo_get_stats64 = ipoib_get_stats,
.ndo_eth_ioctl = ipoib_ioctl,

View File

@ -191,7 +191,7 @@ static int ttusbir_probe(struct usb_interface *intf,
tt = kzalloc_obj(*tt);
buffer = kzalloc(5, GFP_KERNEL);
rc = rc_allocate_device(RC_DRIVER_IR_RAW);
if (!tt || !rc || buffer) {
if (!tt || !rc || !buffer) {
ret = -ENOMEM;
goto out;
}

View File

@ -1023,12 +1023,16 @@ mt7530_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
unsigned int age_count;
unsigned int age_unit;
/* Applied timer is (AGE_CNT + 1) * (AGE_UNIT + 1) seconds */
if (secs < 1 || secs > (AGE_CNT_MAX + 1) * (AGE_UNIT_MAX + 1))
return -ERANGE;
/* iterate through all possible age_count to find the closest pair */
for (tmp_age_count = 0; tmp_age_count <= AGE_CNT_MAX; ++tmp_age_count) {
/* Applied timer is (AGE_CNT + 1) * (AGE_UNIT + 1) seconds.
* The DSA core has already validated the range using
* ds->ageing_time_min and ds->ageing_time_max.
*
* Iterate through all possible age_count values to find the closest
* pair. Start from 1 because the per-entry aging counter is
* initialized to AGE_CNT and a value of 0 means the entry will
* never be aged out.
*/
for (tmp_age_count = 1; tmp_age_count <= AGE_CNT_MAX; ++tmp_age_count) {
unsigned int tmp_age_unit = secs / (tmp_age_count + 1) - 1;
if (tmp_age_unit <= AGE_UNIT_MAX) {
@ -1296,37 +1300,40 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
static void
mt753x_trap_frames(struct mt7530_priv *priv)
{
/* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them
* VLAN-untagged.
/* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress
* them with the EG_TAG attribute set to disabled (system default)
* so that any VLAN tags in the frame are not modified by the
* switch egress VLAN tag processing. This preserves VLAN tags
* for reception on VLAN sub-interfaces.
*/
mt7530_rmw(priv, MT753X_BPC,
PAE_BPDU_FR | PAE_EG_TAG_MASK | PAE_PORT_FW_MASK |
BPDU_EG_TAG_MASK | BPDU_PORT_FW_MASK,
PAE_BPDU_FR | PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
PAE_BPDU_FR | PAE_EG_TAG(MT7530_VLAN_EG_DISABLED) |
PAE_PORT_FW(TO_CPU_FW_CPU_ONLY) |
BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
BPDU_EG_TAG(MT7530_VLAN_EG_DISABLED) |
TO_CPU_FW_CPU_ONLY);
/* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress
* them VLAN-untagged.
/* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and
* egress them with EG_TAG disabled.
*/
mt7530_rmw(priv, MT753X_RGAC1,
R02_BPDU_FR | R02_EG_TAG_MASK | R02_PORT_FW_MASK |
R01_BPDU_FR | R01_EG_TAG_MASK | R01_PORT_FW_MASK,
R02_BPDU_FR | R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
R02_BPDU_FR | R02_EG_TAG(MT7530_VLAN_EG_DISABLED) |
R02_PORT_FW(TO_CPU_FW_CPU_ONLY) | R01_BPDU_FR |
R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
R01_EG_TAG(MT7530_VLAN_EG_DISABLED) |
TO_CPU_FW_CPU_ONLY);
/* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress
* them VLAN-untagged.
/* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and
* egress them with EG_TAG disabled.
*/
mt7530_rmw(priv, MT753X_RGAC2,
R0E_BPDU_FR | R0E_EG_TAG_MASK | R0E_PORT_FW_MASK |
R03_BPDU_FR | R03_EG_TAG_MASK | R03_PORT_FW_MASK,
R0E_BPDU_FR | R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
R0E_BPDU_FR | R0E_EG_TAG(MT7530_VLAN_EG_DISABLED) |
R0E_PORT_FW(TO_CPU_FW_CPU_ONLY) | R03_BPDU_FR |
R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
R03_EG_TAG(MT7530_VLAN_EG_DISABLED) |
TO_CPU_FW_CPU_ONLY);
}
@ -1616,6 +1623,49 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
return 0;
}
static int
mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
{
struct mt7530_dummy_poll p;
u32 val;
int ret;
val = VTCR_BUSY | VTCR_FUNC(cmd) | vid;
mt7530_write(priv, MT7530_VTCR, val);
INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_VTCR);
ret = readx_poll_timeout(_mt7530_read, &p, val,
!(val & VTCR_BUSY), 20, 20000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
return ret;
}
val = mt7530_read(priv, MT7530_VTCR);
if (val & VTCR_INVALID) {
dev_err(priv->dev, "read VTCR invalid\n");
return -EINVAL;
}
return 0;
}
static int
mt7530_setup_vlan0(struct mt7530_priv *priv)
{
u32 val;
/* Validate the entry with independent learning, keep the original
* ingress tag attribute.
*/
val = IVL_MAC | EG_CON | PORT_MEM(MT7530_ALL_MEMBERS) | FID(FID_BRIDGED) |
VLAN_VALID;
mt7530_write(priv, MT7530_VAWD1, val);
mt7530_write(priv, MT7530_VAWD2, 0);
return mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, 0);
}
static void
mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
{
@ -1641,6 +1691,8 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
G0_PORT_VID_DEF);
for (i = 0; i < priv->ds->num_ports; i++) {
if (i == port)
continue;
if (dsa_is_user_port(ds, i) &&
dsa_port_is_vlan_filtering(dsa_to_port(ds, i))) {
all_user_ports_removed = false;
@ -1652,13 +1704,9 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
* the CPU port get out of VLAN filtering mode.
*/
if (all_user_ports_removed) {
struct dsa_port *dp = dsa_to_port(ds, port);
struct dsa_port *cpu_dp = dp->cpu_dp;
mt7530_write(priv, MT7530_PCR_P(cpu_dp->index),
PCR_MATRIX(dsa_user_ports(priv->ds)));
mt7530_write(priv, MT7530_PVC_P(cpu_dp->index), PORT_SPEC_TAG
| PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
mutex_lock(&priv->reg_mutex);
mt7530_setup_vlan0(priv);
mutex_unlock(&priv->reg_mutex);
}
}
@ -1846,33 +1894,6 @@ mt7530_port_mdb_del(struct dsa_switch *ds, int port,
return ret;
}
static int
mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
{
struct mt7530_dummy_poll p;
u32 val;
int ret;
val = VTCR_BUSY | VTCR_FUNC(cmd) | vid;
mt7530_write(priv, MT7530_VTCR, val);
INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_VTCR);
ret = readx_poll_timeout(_mt7530_read, &p, val,
!(val & VTCR_BUSY), 20, 20000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
return ret;
}
val = mt7530_read(priv, MT7530_VTCR);
if (val & VTCR_INVALID) {
dev_err(priv->dev, "read VTCR invalid\n");
return -EINVAL;
}
return 0;
}
static int
mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
struct netlink_ext_ack *extack)
@ -1977,21 +1998,6 @@ mt7530_hw_vlan_update(struct mt7530_priv *priv, u16 vid,
mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, vid);
}
static int
mt7530_setup_vlan0(struct mt7530_priv *priv)
{
u32 val;
/* Validate the entry with independent learning, keep the original
* ingress tag attribute.
*/
val = IVL_MAC | EG_CON | PORT_MEM(MT7530_ALL_MEMBERS) | FID(FID_BRIDGED) |
VLAN_VALID;
mt7530_write(priv, MT7530_VAWD1, val);
return mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, 0);
}
static int
mt7530_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
@ -2004,9 +2010,18 @@ mt7530_port_vlan_add(struct dsa_switch *ds, int port,
mutex_lock(&priv->reg_mutex);
/* VID 0 is managed exclusively by mt7530_setup_vlan0() for
* VLAN-unaware bridge operation. Don't let the bridge overwrite
* its EG_CON flag with VTAG_EN and corrupt PORT_MEM.
*/
if (vlan->vid == 0)
goto skip_vlan_table;
mt7530_hw_vlan_entry_init(&new_entry, port, untagged);
mt7530_hw_vlan_update(priv, vlan->vid, &new_entry, mt7530_hw_vlan_add);
skip_vlan_table:
if (pvid) {
priv->ports[port].pvid = vlan->vid;
@ -2046,10 +2061,15 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
mutex_lock(&priv->reg_mutex);
/* VID 0 is managed exclusively by mt7530_setup_vlan0(). */
if (vlan->vid == 0)
goto skip_vlan_table;
mt7530_hw_vlan_entry_init(&target_entry, port, 0);
mt7530_hw_vlan_update(priv, vlan->vid, &target_entry,
mt7530_hw_vlan_del);
skip_vlan_table:
/* PVID is being restored to the default whenever the PVID port
* is being removed from the VLAN.
*/
@ -2427,7 +2447,10 @@ mt7530_setup(struct dsa_switch *ds)
}
ds->assisted_learning_on_cpu_port = true;
ds->untag_vlan_aware_bridge_pvid = true;
ds->mtu_enforcement_ingress = true;
ds->ageing_time_min = 2 * 1000;
ds->ageing_time_max = (AGE_CNT_MAX + 1) * (AGE_UNIT_MAX + 1) * 1000;
if (priv->id == ID_MT7530) {
regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
@ -2616,7 +2639,10 @@ mt7531_setup_common(struct dsa_switch *ds)
int ret, i;
ds->assisted_learning_on_cpu_port = true;
ds->untag_vlan_aware_bridge_pvid = true;
ds->mtu_enforcement_ingress = true;
ds->ageing_time_min = 2 * 1000;
ds->ageing_time_max = (AGE_CNT_MAX + 1) * (AGE_UNIT_MAX + 1) * 1000;
mt753x_trap_frames(priv);

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,20 @@ config NET_VENDOR_3COM
if NET_VENDOR_3COM
config EL3
tristate "3c509/3c579 \"EtherLink III\" support"
depends on (ISA || EISA)
help
If you have a network (Ethernet) card belonging to the 3Com
EtherLinkIII series, say Y here.
If your card is not working you may need to use the DOS
setup disk to disable Plug & Play mode, and to select the default
media type.
To compile this driver as a module, choose M here. The module
will be called 3c509.
config VORTEX
tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
depends on (PCI || EISA) && HAS_IOPORT_MAP

View File

@ -3,5 +3,6 @@
# Makefile for the 3Com Ethernet device drivers
#
obj-$(CONFIG_EL3) += 3c509.o
obj-$(CONFIG_VORTEX) += 3c59x.o
obj-$(CONFIG_TYPHOON) += typhoon.o

View File

@ -1793,11 +1793,8 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
u32 val, pse_port, chan;
int i, src_port;
/* Forward the traffic to the proper GDM port */
pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3
: FE_PSE_PORT_GDM4;
airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
pse_port);
FE_PSE_PORT_DROP);
airoha_fe_clear(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
GDM_STRIP_CRC_MASK);
@ -1815,6 +1812,11 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK,
FIELD_PREP(GDM_SHORT_LEN_MASK, 60) |
FIELD_PREP(GDM_LONG_LEN_MASK, AIROHA_MAX_MTU));
/* Forward the traffic to the proper GDM port */
pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3
: FE_PSE_PORT_GDM4;
airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
pse_port);
/* Disable VIP and IFC for GDM2 */
airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));

View File

@ -64,9 +64,14 @@ DEFINE_SHOW_ATTRIBUTE(identity);
void pdsc_debugfs_add_ident(struct pdsc *pdsc)
{
struct dentry *dentry;
/* This file will already exist in the reset flow */
if (debugfs_lookup("identity", pdsc->dentry))
dentry = debugfs_lookup("identity", pdsc->dentry);
if (!IS_ERR_OR_NULL(dentry)) {
dput(dentry);
return;
}
debugfs_create_file("identity", 0400, pdsc->dentry,
pdsc, &identity_fops);

View File

@ -162,12 +162,19 @@ static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds)
dev_dbg(dev, "DEVCMD %d %s after %ld secs\n",
opcode, pdsc_devcmd_str(opcode), duration / HZ);
if ((!done || timeout) && running) {
if (!running) {
dev_err(dev, "DEVCMD %d %s fw not running\n",
opcode, pdsc_devcmd_str(opcode));
pdsc_devcmd_clean(pdsc);
return -ENXIO;
}
if (!done || timeout) {
dev_err(dev, "DEVCMD %d %s timeout, done %d timeout %d max_seconds=%d\n",
opcode, pdsc_devcmd_str(opcode), done, timeout,
max_seconds);
err = -ETIMEDOUT;
pdsc_devcmd_clean(pdsc);
return -ETIMEDOUT;
}
status = pdsc_devcmd_status(pdsc);

View File

@ -122,12 +122,14 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
listlen = min(fw_list.num_fw_slots, ARRAY_SIZE(fw_list.fw_names));
for (i = 0; i < listlen; i++) {
char *fw_ver = fw_list.fw_names[i].fw_version;
if (i < ARRAY_SIZE(fw_slotnames))
strscpy(buf, fw_slotnames[i], sizeof(buf));
else
snprintf(buf, sizeof(buf), "fw.slot_%d", i);
err = devlink_info_version_stored_put(req, buf,
fw_list.fw_names[i].fw_version);
fw_ver[sizeof(fw_list.fw_names[i].fw_version) - 1] = '\0';
err = devlink_info_version_stored_put(req, buf, fw_ver);
if (err)
return err;
}

View File

@ -1856,6 +1856,9 @@ static int ag71xx_probe(struct platform_device *pdev)
ag71xx_int_disable(ag, AG71XX_INT_POLL);
ndev->irq = platform_get_irq(pdev, 0);
if (ndev->irq < 0)
return ndev->irq;
err = devm_request_irq(&pdev->dev, ndev->irq, ag71xx_interrupt,
0x0, dev_name(&pdev->dev), ndev);
if (err) {

View File

@ -1368,13 +1368,12 @@ void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)
reg &= ~(TBUF_EEE_EN | TBUF_PM_EN);
bcmgenet_writel(reg, priv->base + off);
/* Do the same for thing for RBUF */
/* RBUF EEE/PM can break the RX path on GENET. Keep it disabled. */
reg = bcmgenet_rbuf_readl(priv, RBUF_ENERGY_CTRL);
if (enable)
reg |= RBUF_EEE_EN | RBUF_PM_EN;
else
if (reg & (RBUF_EEE_EN | RBUF_PM_EN)) {
reg &= ~(RBUF_EEE_EN | RBUF_PM_EN);
bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL);
bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL);
}
if (!enable && priv->clk_eee_enabled) {
clk_disable_unprepare(priv->clk_eee);

View File

@ -56,11 +56,21 @@ static inline u32 enetc_vsi_set_msize(u32 size)
}
#define ENETC_PSIMSGRR 0x204
#define ENETC_PSIMSGRR_MR_MASK GENMASK(2, 1)
#define ENETC_PSIMSGRR_MR(n) BIT((n) + 1) /* n = VSI index */
#define ENETC_PSIVMSGRCVAR0(n) (0x210 + (n) * 0x8) /* n = VSI index */
#define ENETC_PSIVMSGRCVAR1(n) (0x214 + (n) * 0x8)
/* Message received mask, n is the active number of VSIs.
* It is available for ENETC_PSIMSGRR, ENETC_PSIIER, and
* ENETC_PSIIDR registers.
*/
#define ENETC_PSIMR_MASK(n) \
({ typeof(n) _n = (n); (_n) ? GENMASK((_n), 1) : 0; })
/* Message received bit, n is VSI index. It is available for
* ENETC_PSIMSGRR, ENETC_PSIIER, and ENETC_PSIIDR registers.
*/
#define ENETC_PSIMR_BIT(n) BIT((n) + 1)
#define ENETC_VSIMSGSR 0x204 /* RO */
#define ENETC_VSIMSGSR_MB BIT(0)
#define ENETC_VSIMSGSR_MS BIT(1)
@ -94,7 +104,6 @@ static inline u32 enetc_vsi_set_msize(u32 size)
#define ENETC_SICAPR1 0x904
#define ENETC_PSIIER 0xa00
#define ENETC_PSIIER_MR_MASK GENMASK(2, 1)
#define ENETC_PSIIDR 0xa08
#define ENETC_SITXIDR 0xa18
#define ENETC_SIRXIDR 0xa28

View File

@ -3,18 +3,25 @@
#include "enetc_pf.h"
static void enetc_msg_disable_mr_int(struct enetc_hw *hw)
static void enetc_msg_disable_mr_int(struct enetc_pf *pf)
{
u32 psiier = enetc_rd(hw, ENETC_PSIIER);
struct enetc_hw *hw = &pf->si->hw;
u32 psiier;
psiier = enetc_rd(hw, ENETC_PSIIER) & ~ENETC_PSIMR_MASK(pf->num_vfs);
/* disable MR int source(s) */
enetc_wr(hw, ENETC_PSIIER, psiier & ~ENETC_PSIIER_MR_MASK);
enetc_wr(hw, ENETC_PSIIER, psiier);
}
static void enetc_msg_enable_mr_int(struct enetc_hw *hw)
static void enetc_msg_enable_mr_int(struct enetc_pf *pf)
{
u32 psiier = enetc_rd(hw, ENETC_PSIIER);
struct enetc_hw *hw = &pf->si->hw;
u32 psiier;
enetc_wr(hw, ENETC_PSIIER, psiier | ENETC_PSIIER_MR_MASK);
psiier = enetc_rd(hw, ENETC_PSIIER) | ENETC_PSIMR_MASK(pf->num_vfs);
enetc_wr(hw, ENETC_PSIIER, psiier);
}
static irqreturn_t enetc_msg_psi_msix(int irq, void *data)
@ -22,7 +29,7 @@ static irqreturn_t enetc_msg_psi_msix(int irq, void *data)
struct enetc_si *si = (struct enetc_si *)data;
struct enetc_pf *pf = enetc_si_priv(si);
enetc_msg_disable_mr_int(&si->hw);
enetc_msg_disable_mr_int(pf);
schedule_work(&pf->msg_task);
return IRQ_HANDLED;
@ -31,33 +38,35 @@ static irqreturn_t enetc_msg_psi_msix(int irq, void *data)
static void enetc_msg_task(struct work_struct *work)
{
struct enetc_pf *pf = container_of(work, struct enetc_pf, msg_task);
u32 mr_mask = ENETC_PSIMR_MASK(pf->num_vfs);
struct enetc_hw *hw = &pf->si->hw;
unsigned long mr_mask;
u32 mr_status;
int i;
for (;;) {
mr_mask = enetc_rd(hw, ENETC_PSIMSGRR) & ENETC_PSIMSGRR_MR_MASK;
if (!mr_mask) {
/* re-arm MR interrupts, w1c the IDR reg */
enetc_wr(hw, ENETC_PSIIDR, ENETC_PSIIER_MR_MASK);
enetc_msg_enable_mr_int(hw);
return;
}
mr_status = (enetc_rd(hw, ENETC_PSIMSGRR) & mr_mask) |
(enetc_rd(hw, ENETC_PSIIDR) & mr_mask);
if (!mr_status)
goto out;
for (i = 0; i < pf->num_vfs; i++) {
u32 psimsgrr;
u16 msg_code;
for (i = 0; i < pf->num_vfs; i++) {
u32 psimsgrr;
u16 msg_code;
if (!(ENETC_PSIMSGRR_MR(i) & mr_mask))
continue;
if (!(ENETC_PSIMR_BIT(i) & mr_status))
continue;
enetc_msg_handle_rxmsg(pf, i, &msg_code);
enetc_msg_handle_rxmsg(pf, i, &msg_code);
psimsgrr = ENETC_SIMSGSR_SET_MC(msg_code);
psimsgrr |= ENETC_PSIMSGRR_MR(i); /* w1c */
enetc_wr(hw, ENETC_PSIMSGRR, psimsgrr);
}
/* w1c to clear the corresponding VF MR bit */
enetc_wr(hw, ENETC_PSIIDR, ENETC_PSIMR_BIT(i));
psimsgrr = ENETC_SIMSGSR_SET_MC(msg_code);
psimsgrr |= ENETC_PSIMR_BIT(i); /* w1c */
enetc_wr(hw, ENETC_PSIMSGRR, psimsgrr);
}
out:
enetc_msg_enable_mr_int(pf);
}
/* Init */
@ -96,12 +105,12 @@ static void enetc_msg_free_mbx(struct enetc_si *si, int idx)
struct enetc_hw *hw = &si->hw;
struct enetc_msg_swbd *msg;
enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), 0);
enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), 0);
msg = &pf->rxmsg[idx];
dma_free_coherent(&si->pdev->dev, msg->size, msg->vaddr, msg->dma);
memset(msg, 0, sizeof(*msg));
enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), 0);
enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), 0);
}
int enetc_msg_psi_init(struct enetc_pf *pf)
@ -109,6 +118,15 @@ int enetc_msg_psi_init(struct enetc_pf *pf)
struct enetc_si *si = pf->si;
int vector, i, err;
for (i = 0; i < pf->num_vfs; i++) {
err = enetc_msg_alloc_mbx(si, i);
if (err)
goto free_mbx;
}
/* initialize PSI mailbox */
INIT_WORK(&pf->msg_task, enetc_msg_task);
/* register message passing interrupt handler */
snprintf(pf->msg_int_name, sizeof(pf->msg_int_name), "%s-vfmsg",
si->ndev->name);
@ -117,32 +135,21 @@ int enetc_msg_psi_init(struct enetc_pf *pf)
if (err) {
dev_err(&si->pdev->dev,
"PSI messaging: request_irq() failed!\n");
return err;
goto free_mbx;
}
/* set one IRQ entry for PSI message receive notification (SI int) */
enetc_wr(&si->hw, ENETC_SIMSIVR, ENETC_SI_INT_IDX);
/* initialize PSI mailbox */
INIT_WORK(&pf->msg_task, enetc_msg_task);
for (i = 0; i < pf->num_vfs; i++) {
err = enetc_msg_alloc_mbx(si, i);
if (err)
goto err_init_mbx;
}
/* enable MR interrupts */
enetc_msg_enable_mr_int(&si->hw);
enetc_msg_enable_mr_int(pf);
return 0;
err_init_mbx:
free_mbx:
for (i--; i >= 0; i--)
enetc_msg_free_mbx(si, i);
free_irq(vector, si);
return err;
}
@ -151,14 +158,17 @@ void enetc_msg_psi_free(struct enetc_pf *pf)
struct enetc_si *si = pf->si;
int i;
cancel_work_sync(&pf->msg_task);
/* disable MR interrupts */
enetc_msg_disable_mr_int(&si->hw);
for (i = 0; i < pf->num_vfs; i++)
enetc_msg_free_mbx(si, i);
enetc_msg_disable_mr_int(pf);
/* de-register message passing interrupt handler */
free_irq(pci_irq_vector(si->pdev, ENETC_SI_INT_IDX), si);
cancel_work_sync(&pf->msg_task);
/* MR interrupts may be re-enabled by workqueue */
enetc_msg_disable_mr_int(pf);
for (i = 0; i < pf->num_vfs; i++)
enetc_msg_free_mbx(si, i);
}

View File

@ -252,8 +252,12 @@ static int enetc_pf_set_vf_mac(struct net_device *ndev, int vf, u8 *mac)
return -EADDRNOTAVAIL;
vf_state = &pf->vf_state[vf];
mutex_lock(&vf_state->lock);
vf_state->flags |= ENETC_VF_FLAG_PF_SET_MAC;
enetc_pf_set_primary_mac_addr(&priv->si->hw, vf + 1, mac);
mutex_unlock(&vf_state->lock);
return 0;
}
@ -478,49 +482,77 @@ static void enetc_configure_port(struct enetc_pf *pf)
/* Messaging */
static u16 enetc_msg_pf_set_vf_primary_mac_addr(struct enetc_pf *pf,
int vf_id)
int vf_id, void *msg)
{
struct enetc_vf_state *vf_state = &pf->vf_state[vf_id];
struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id];
struct enetc_msg_cmd_set_primary_mac *cmd;
struct enetc_msg_cmd_set_primary_mac *cmd = msg;
struct device *dev = &pf->si->pdev->dev;
u16 cmd_id;
u16 cmd_id = cmd->header.id;
char *addr;
cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
cmd_id = cmd->header.id;
if (cmd_id != ENETC_MSG_CMD_MNG_ADD)
return ENETC_MSG_CMD_STATUS_FAIL;
addr = cmd->mac.sa_data;
if (vf_state->flags & ENETC_VF_FLAG_PF_SET_MAC)
dev_warn(dev, "Attempt to override PF set mac addr for VF%d\n",
vf_id);
else
enetc_pf_set_primary_mac_addr(&pf->si->hw, vf_id + 1, addr);
if (!is_valid_ether_addr(addr)) {
dev_err_ratelimited(dev, "VF%d attempted to set invalid MAC\n",
vf_id);
return ENETC_MSG_CMD_STATUS_FAIL;
}
mutex_lock(&vf_state->lock);
if (vf_state->flags & ENETC_VF_FLAG_PF_SET_MAC) {
mutex_unlock(&vf_state->lock);
dev_err_ratelimited(dev,
"VF%d attempted to override PF set MAC\n",
vf_id);
return ENETC_MSG_CMD_STATUS_FAIL;
}
enetc_pf_set_primary_mac_addr(&pf->si->hw, vf_id + 1, addr);
mutex_unlock(&vf_state->lock);
return ENETC_MSG_CMD_STATUS_OK;
}
void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int vf_id, u16 *status)
{
struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id];
struct enetc_msg_swbd *msg_swbd = &pf->rxmsg[vf_id];
struct device *dev = &pf->si->pdev->dev;
struct enetc_msg_cmd_header *cmd_hdr;
u16 cmd_type;
u8 *msg;
*status = ENETC_MSG_CMD_STATUS_OK;
cmd_hdr = (struct enetc_msg_cmd_header *)msg->vaddr;
msg = kzalloc_objs(*msg, msg_swbd->size);
if (!msg) {
dev_err_ratelimited(dev,
"Failed to allocate message buffer\n");
*status = ENETC_MSG_CMD_STATUS_FAIL;
return;
}
/* Currently, only ENETC_MSG_CMD_MNG_MAC command is supported, so
* only sizeof(struct enetc_msg_cmd_set_primary_mac) bytes need to
* be copied. This data already includes the cmd_type field, so it
* can correctly return an error code.
*/
memcpy(msg, msg_swbd->vaddr,
sizeof(struct enetc_msg_cmd_set_primary_mac));
cmd_hdr = (struct enetc_msg_cmd_header *)msg;
cmd_type = cmd_hdr->type;
switch (cmd_type) {
case ENETC_MSG_CMD_MNG_MAC:
*status = enetc_msg_pf_set_vf_primary_mac_addr(pf, vf_id);
*status = enetc_msg_pf_set_vf_primary_mac_addr(pf, vf_id, msg);
break;
default:
dev_err(dev, "command not supported (cmd_type: 0x%x)\n",
cmd_type);
*status = ENETC_MSG_CMD_STATUS_FAIL;
dev_err_ratelimited(dev,
"command not supported (cmd_type: 0x%x)\n",
cmd_type);
}
kfree(msg);
}
#ifdef CONFIG_PCI_IOV
@ -531,9 +563,9 @@ static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs)
int err;
if (!num_vfs) {
pci_disable_sriov(pdev);
enetc_msg_psi_free(pf);
pf->num_vfs = 0;
pci_disable_sriov(pdev);
} else {
pf->num_vfs = num_vfs;
@ -960,8 +992,13 @@ static int enetc_pf_probe(struct pci_dev *pdev,
if (pf->total_vfs) {
pf->vf_state = kzalloc_objs(struct enetc_vf_state,
pf->total_vfs);
if (!pf->vf_state)
if (!pf->vf_state) {
err = -ENOMEM;
goto err_alloc_vf_state;
}
for (int i = 0; i < pf->total_vfs; i++)
mutex_init(&pf->vf_state[i].lock);
}
err = enetc_setup_mac_addresses(node, pf);

View File

@ -14,6 +14,7 @@ enum enetc_vf_flags {
};
struct enetc_vf_state {
struct mutex lock; /* Prevent concurrent access */
enum enetc_vf_flags flags;
};

View File

@ -3682,7 +3682,7 @@ int ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
ret = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
ICE_MCAST_VLAN_PROMISC_BITS,
vid);
if (ret)
if (ret && ret != -EEXIST)
goto finish;
}
@ -4104,6 +4104,12 @@ int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked)
}
ice_pf_dcb_recfg(pf, locked);
ice_vsi_open(vsi);
/* Rx rings are reallocated during VSI rebuild and lose their ptp_rx
* flag. Restore timestamp mode so newly allocated rings are set up
* for hardware Rx timestamping.
*/
if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags))
ice_ptp_restore_timestamp_mode(pf);
goto done;
rebuild_err:

View File

@ -2141,16 +2141,23 @@ int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port)
}
incval = (u64)hi << 32 | lo;
if (!ice_ptp_lock(hw)) {
dev_err(ice_hw_to_dev(hw), "Failed to acquire PTP semaphore\n");
return -EBUSY;
}
err = ice_write_40b_ptp_reg_eth56g(hw, port, PHY_REG_TIMETUS_L, incval);
if (err)
return err;
goto err_ptp_unlock;
err = ice_ptp_one_port_cmd(hw, port, ICE_PTP_INIT_INCVAL);
if (err)
return err;
goto err_ptp_unlock;
ice_ptp_exec_tmr_cmd(hw);
ice_ptp_unlock(hw);
err = ice_sync_phy_timer_eth56g(hw, port);
if (err)
return err;
@ -2166,6 +2173,10 @@ int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port)
ice_debug(hw, ICE_DBG_PTP, "Enabled clock on PHY port %u\n", port);
return 0;
err_ptp_unlock:
ice_ptp_unlock(hw);
return err;
}
/**
@ -4503,18 +4514,17 @@ static int
ice_read_phy_tstamp_ll_e810(struct ice_hw *hw, u8 idx, u8 *hi, u32 *lo)
{
struct ice_e810_params *params = &hw->ptp.phy.e810;
unsigned long flags;
u32 val;
int err;
spin_lock_irqsave(&params->atqbal_wq.lock, flags);
spin_lock_irq(&params->atqbal_wq.lock);
/* Wait for any pending in-progress low latency interrupt */
err = wait_event_interruptible_locked_irq(params->atqbal_wq,
!(params->atqbal_flags &
ATQBAL_FLAGS_INTR_IN_PROGRESS));
if (err) {
spin_unlock_irqrestore(&params->atqbal_wq.lock, flags);
spin_unlock_irq(&params->atqbal_wq.lock);
return err;
}
@ -4529,7 +4539,7 @@ ice_read_phy_tstamp_ll_e810(struct ice_hw *hw, u8 idx, u8 *hi, u32 *lo)
REG_LL_PROXY_H);
if (err) {
ice_debug(hw, ICE_DBG_PTP, "Failed to read PTP timestamp using low latency read\n");
spin_unlock_irqrestore(&params->atqbal_wq.lock, flags);
spin_unlock_irq(&params->atqbal_wq.lock);
return err;
}
@ -4539,7 +4549,7 @@ ice_read_phy_tstamp_ll_e810(struct ice_hw *hw, u8 idx, u8 *hi, u32 *lo)
/* Read the low 32 bit value and set the TS valid bit */
*lo = rd32(hw, REG_LL_PROXY_L) | TS_VALID;
spin_unlock_irqrestore(&params->atqbal_wq.lock, flags);
spin_unlock_irq(&params->atqbal_wq.lock);
return 0;
}
@ -5254,9 +5264,13 @@ static void ice_ptp_init_phy_e830(struct ice_ptp_hw *ptp)
*/
bool ice_ptp_lock(struct ice_hw *hw)
{
struct ice_pf *pf = container_of(hw, struct ice_pf, hw);
u32 hw_lock;
int i;
if (!ice_is_primary(hw))
hw = ice_get_primary_hw(pf);
#define MAX_TRIES 15
for (i = 0; i < MAX_TRIES; i++) {
@ -5283,6 +5297,11 @@ bool ice_ptp_lock(struct ice_hw *hw)
*/
void ice_ptp_unlock(struct ice_hw *hw)
{
struct ice_pf *pf = container_of(hw, struct ice_pf, hw);
if (!ice_is_primary(hw))
hw = ice_get_primary_hw(pf);
wr32(hw, PFTSYN_SEM + (PFTSYN_SEM_BYTES * hw->pf_id), 0);
}

View File

@ -840,7 +840,7 @@ int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
if (qpi->rxq.databuffer_size != 0 &&
(qpi->rxq.databuffer_size > ((16 * 1024) - 128) ||
qpi->rxq.databuffer_size < 1024))
qpi->rxq.databuffer_size < 128))
goto error_param;
ring->rx_buf_len = qpi->rxq.databuffer_size;

View File

@ -34,6 +34,7 @@ static int igc_fpe_init_smd_frame(struct igc_ring *ring,
return -ENOMEM;
}
buffer->type = IGC_TX_BUFFER_TYPE_SKB;
buffer->skb = skb;
buffer->protocol = 0;
buffer->bytecount = skb->len;
@ -109,10 +110,16 @@ static int igc_fpe_xmit_smd_frame(struct igc_adapter *adapter,
__netif_tx_lock(nq, cpu);
err = igc_fpe_init_tx_descriptor(ring, skb, type);
if (err)
goto err_free_skb_any;
igc_flush_tx_descriptors(ring);
__netif_tx_unlock(nq);
return 0;
err_free_skb_any:
__netif_tx_unlock(nq);
dev_kfree_skb_any(skb);
return err;
}

View File

@ -1221,6 +1221,7 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
ether_addr_equal(rx_ring->netdev->dev_addr,
eth_hdr(skb)->h_source)) {
dev_kfree_skb_irq(skb);
skb = NULL;
continue;
}

View File

@ -1294,13 +1294,18 @@ static inline void link_status_user_format(u64 lstat,
struct cgx_link_user_info *linfo,
struct cgx *cgx, u8 lmac_id)
{
unsigned int speed;
linfo->link_up = FIELD_GET(RESP_LINKSTAT_UP, lstat);
linfo->full_duplex = FIELD_GET(RESP_LINKSTAT_FDUPLEX, lstat);
linfo->speed = cgx_speed_mbps[FIELD_GET(RESP_LINKSTAT_SPEED, lstat)];
linfo->an = FIELD_GET(RESP_LINKSTAT_AN, lstat);
linfo->fec = FIELD_GET(RESP_LINKSTAT_FEC, lstat);
linfo->lmac_type_id = FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, lstat);
speed = FIELD_GET(RESP_LINKSTAT_SPEED, lstat);
linfo->speed = speed < ARRAY_SIZE(cgx_speed_mbps) ?
cgx_speed_mbps[speed] : 0;
if (linfo->lmac_type_id >= LMAC_MODE_MAX) {
dev_err(&cgx->pdev->dev, "Unknown lmac_type_id %d reported by firmware on cgx port%d:%d",
linfo->lmac_type_id, cgx->cgx_id, lmac_id);

View File

@ -990,7 +990,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
u16 vf_func;
/* Only CGX PF/VF can add allmulticast entry */
if (is_lbk_vf(rvu, pcifunc) && is_sdp_vf(rvu, pcifunc))
if (is_lbk_vf(rvu, pcifunc) || is_sdp_vf(rvu, pcifunc))
return;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);

View File

@ -619,11 +619,13 @@ static int cn20k_pool_aq_init(struct otx2_nic *pfvf, u16 pool_id,
err = otx2_sync_mbox_msg(&pfvf->mbox);
if (err) {
qmem_free(pfvf->dev, pool->stack);
pool->stack = NULL;
return err;
}
aq = otx2_mbox_alloc_msg_npa_cn20k_aq_enq(&pfvf->mbox);
if (!aq) {
qmem_free(pfvf->dev, pool->stack);
pool->stack = NULL;
return -ENOMEM;
}
}

View File

@ -1482,11 +1482,13 @@ int otx2_pool_aq_init(struct otx2_nic *pfvf, u16 pool_id,
err = otx2_sync_mbox_msg(&pfvf->mbox);
if (err) {
qmem_free(pfvf->dev, pool->stack);
pool->stack = NULL;
return err;
}
aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
if (!aq) {
qmem_free(pfvf->dev, pool->stack);
pool->stack = NULL;
return -ENOMEM;
}
}

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