mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
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:
commit
37f32d5ab8
2
.mailmap
2
.mailmap
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
---------------------
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
249
Documentation/networking/device_drivers/ethernet/3com/3c509.rst
Normal file
249
Documentation/networking/device_drivers/ethernet/3com/3c509.rst
Normal 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
|
||||
|
||||
|
|
@ -10,6 +10,7 @@ Contents:
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
3com/3c509
|
||||
3com/vortex
|
||||
amazon/ena
|
||||
altera/altera_tse
|
||||
|
|
|
|||
15
MAINTAINERS
15
MAINTAINERS
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ b_clk: b {
|
|||
clock-div = <3>;
|
||||
};
|
||||
|
||||
bsc: bus {
|
||||
bsc: bus@0 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ aliases {
|
|||
spi2 = &hspi2;
|
||||
};
|
||||
|
||||
lbsc: bus {
|
||||
lbsc: bus@0 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -704,7 +704,7 @@ R8A7779_CLK_MMC1 R8A7779_CLK_MMC0
|
|||
};
|
||||
};
|
||||
|
||||
lbsc: bus {
|
||||
lbsc: bus@0 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ extal_clk: extal {
|
|||
bootph-all;
|
||||
};
|
||||
|
||||
lbsc: bus {
|
||||
lbsc: bus@0 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1327,6 +1327,7 @@ usb20phyrst: usb20phy-reset@15830000 {
|
|||
resets = <&cpg 0xaf>;
|
||||
power-domains = <&cpg>;
|
||||
#reset-cells = <0>;
|
||||
#mux-state-cells = <1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
10
arch/arm64/include/asm/ring_buffer.h
Normal file
10
arch/arm64/include/asm/ring_buffer.h
Normal 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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
1543
drivers/net/ethernet/3com/3c509.c
Normal file
1543
drivers/net/ethernet/3com/3c509.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ enum enetc_vf_flags {
|
|||
};
|
||||
|
||||
struct enetc_vf_state {
|
||||
struct mutex lock; /* Prevent concurrent access */
|
||||
enum enetc_vf_flags flags;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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(¶ms->atqbal_wq.lock, flags);
|
||||
spin_lock_irq(¶ms->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(¶ms->atqbal_wq.lock, flags);
|
||||
spin_unlock_irq(¶ms->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(¶ms->atqbal_wq.lock, flags);
|
||||
spin_unlock_irq(¶ms->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(¶ms->atqbal_wq.lock, flags);
|
||||
spin_unlock_irq(¶ms->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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue
Block a user