Import of kernel-6.12.0-211.20.1.el10_2
This commit is contained in:
parent
f33fa76b71
commit
c23a26575f
@ -65,35 +65,43 @@ request, where user provides attributes that result in single pin match.
|
||||
Pin selection
|
||||
=============
|
||||
|
||||
In general, selected pin (the one which signal is driving the dpll
|
||||
device) can be obtained from ``DPLL_A_PIN_STATE`` attribute, and only
|
||||
one pin shall be in ``DPLL_PIN_STATE_CONNECTED`` state for any dpll
|
||||
device.
|
||||
Pin state (``DPLL_A_PIN_STATE``) reflects the administrative intent set
|
||||
by the user. Pin operational state (``DPLL_A_PIN_OPERSTATE``) reflects
|
||||
what the hardware is actually doing with the pin.
|
||||
|
||||
Pin selection can be done either manually or automatically, depending
|
||||
on hardware capabilities and active dpll device work mode
|
||||
(``DPLL_A_MODE`` attribute). The consequence is that there are
|
||||
differences for each mode in terms of available pin states, as well as
|
||||
for the states the user can request for a dpll device.
|
||||
differences for each mode in terms of available pin states the user can
|
||||
request for a dpll device.
|
||||
|
||||
In manual mode (``DPLL_MODE_MANUAL``) the user can request or receive
|
||||
one of following pin states:
|
||||
In manual mode (``DPLL_MODE_MANUAL``) the user can request one of
|
||||
following pin states:
|
||||
|
||||
- ``DPLL_PIN_STATE_CONNECTED`` - the pin is used to drive dpll device
|
||||
- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not used to drive dpll
|
||||
- ``DPLL_PIN_STATE_CONNECTED`` - the pin is selected to drive dpll
|
||||
device
|
||||
- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not selected to drive
|
||||
dpll device
|
||||
|
||||
In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request or
|
||||
receive one of following pin states:
|
||||
In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request one of
|
||||
following pin states:
|
||||
|
||||
- ``DPLL_PIN_STATE_SELECTABLE`` - the pin shall be considered as valid
|
||||
input for automatic selection algorithm
|
||||
- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin shall be not considered as
|
||||
a valid input for automatic selection algorithm
|
||||
|
||||
In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can only receive
|
||||
pin state ``DPLL_PIN_STATE_CONNECTED`` once automatic selection
|
||||
algorithm locks a dpll device with one of the inputs.
|
||||
The actual hardware status of a pin is reported via the operational
|
||||
state (``DPLL_A_PIN_OPERSTATE``) attribute nested under the parent
|
||||
device:
|
||||
|
||||
- ``DPLL_PIN_OPERSTATE_ACTIVE`` - pin is qualified and actively used
|
||||
by the DPLL
|
||||
- ``DPLL_PIN_OPERSTATE_STANDBY`` - pin is qualified but not actively
|
||||
used by the DPLL
|
||||
- ``DPLL_PIN_OPERSTATE_NO_SIGNAL`` - pin does not have a valid signal
|
||||
- ``DPLL_PIN_OPERSTATE_QUAL_FAILED`` - pin signal failed qualification
|
||||
checks
|
||||
|
||||
Shared pins
|
||||
===========
|
||||
@ -250,6 +258,44 @@ in the ``DPLL_A_PIN_PHASE_OFFSET`` attribute.
|
||||
``DPLL_A_PHASE_OFFSET_MONITOR`` attr state of a feature
|
||||
=============================== ========================
|
||||
|
||||
Fractional frequency offset
|
||||
===========================
|
||||
|
||||
The fractional frequency offset (FFO) is reported through two attributes
|
||||
that carry the same measurement at different precisions:
|
||||
|
||||
- ``DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET`` in PPM (parts per million)
|
||||
- ``DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT`` in PPT (parts per trillion)
|
||||
|
||||
Both attributes appear at the top level of a pin and inside each
|
||||
``pin-parent-device`` nest. Two FFO types are defined:
|
||||
|
||||
- ``DPLL_FFO_PORT_RXTX_RATE`` - RX vs TX symbol rate offset (top-level)
|
||||
- ``DPLL_FFO_PIN_DEVICE`` - pin vs parent DPLL offset (per-parent)
|
||||
|
||||
The driver declares which types it supports via the ``supported_ffo``
|
||||
bitmask in ``struct dpll_pin_ops``. The core only calls the ``ffo_get``
|
||||
callback for types the driver has opted into. The requested type is
|
||||
passed to the driver in the ``struct dpll_ffo_param``.
|
||||
|
||||
Frequency monitor
|
||||
=================
|
||||
|
||||
Some DPLL devices may offer the capability to measure the actual
|
||||
frequency of all available input pins. The attribute and current feature state
|
||||
shall be included in the response message of the ``DPLL_CMD_DEVICE_GET``
|
||||
command for supported DPLL devices. In such cases, users can also control
|
||||
the feature using the ``DPLL_CMD_DEVICE_SET`` command by setting the
|
||||
``enum dpll_feature_state`` values for the attribute.
|
||||
Once enabled the measured input frequency for each input pin shall be
|
||||
returned in the ``DPLL_A_PIN_MEASURED_FREQUENCY`` attribute. The value
|
||||
is in millihertz (mHz), using ``DPLL_PIN_MEASURED_FREQUENCY_DIVIDER``
|
||||
as the divider.
|
||||
|
||||
=============================== ========================
|
||||
``DPLL_A_FREQUENCY_MONITOR`` attr state of a feature
|
||||
=============================== ========================
|
||||
|
||||
Embedded SYNC
|
||||
=============
|
||||
|
||||
@ -411,6 +457,8 @@ according to attribute purpose.
|
||||
``DPLL_A_PIN_STATE`` attr state of pin on the parent
|
||||
pin
|
||||
``DPLL_A_PIN_CAPABILITIES`` attr bitmask of pin capabilities
|
||||
``DPLL_A_PIN_MEASURED_FREQUENCY`` attr measured frequency of
|
||||
an input pin in mHz
|
||||
==================================== ==================================
|
||||
|
||||
==================================== =================================
|
||||
|
||||
@ -212,6 +212,27 @@ definitions:
|
||||
name: selectable
|
||||
doc: pin enabled for automatic input selection
|
||||
render-max: true
|
||||
-
|
||||
type: enum
|
||||
name: pin-operstate
|
||||
doc: |
|
||||
defines possible operational states of a pin with respect to its
|
||||
parent DPLL device, valid values for DPLL_A_PIN_OPERSTATE attribute
|
||||
entries:
|
||||
-
|
||||
name: active
|
||||
doc: pin is qualified and actively used by the DPLL
|
||||
value: 1
|
||||
-
|
||||
name: standby
|
||||
doc: pin is qualified but not actively used by the DPLL
|
||||
-
|
||||
name: no-signal
|
||||
doc: pin does not have a valid signal
|
||||
-
|
||||
name: qual-failed
|
||||
doc: pin signal failed qualification (e.g. frequency or phase monitor)
|
||||
render-max: true
|
||||
-
|
||||
type: flags
|
||||
name: pin-capabilities
|
||||
@ -240,6 +261,20 @@ definitions:
|
||||
integer part of a measured phase offset value.
|
||||
Value of (DPLL_A_PHASE_OFFSET % DPLL_PHASE_OFFSET_DIVIDER) is a
|
||||
fractional part of a measured phase offset value.
|
||||
-
|
||||
type: const
|
||||
name: pin-measured-frequency-divider
|
||||
value: 1000
|
||||
doc: |
|
||||
pin measured frequency divider allows userspace to calculate
|
||||
a value of measured input frequency as a fractional value with
|
||||
three digit decimal precision (millihertz).
|
||||
Value of (DPLL_A_PIN_MEASURED_FREQUENCY /
|
||||
DPLL_PIN_MEASURED_FREQUENCY_DIVIDER) is an integer part of
|
||||
a measured frequency value.
|
||||
Value of (DPLL_A_PIN_MEASURED_FREQUENCY %
|
||||
DPLL_PIN_MEASURED_FREQUENCY_DIVIDER) is a fractional part of
|
||||
a measured frequency value.
|
||||
-
|
||||
type: enum
|
||||
name: feature-state
|
||||
@ -319,6 +354,13 @@ attribute-sets:
|
||||
name: phase-offset-avg-factor
|
||||
type: u32
|
||||
doc: Averaging factor applied to calculation of reported phase offset.
|
||||
-
|
||||
name: frequency-monitor
|
||||
type: u32
|
||||
enum: feature-state
|
||||
doc: Current or desired state of the frequency monitor feature.
|
||||
If enabled, dpll device shall measure all currently available
|
||||
inputs for their actual input frequency.
|
||||
-
|
||||
name: pin
|
||||
enum-name: dpll_a_pin
|
||||
@ -406,12 +448,14 @@ attribute-sets:
|
||||
name: fractional-frequency-offset
|
||||
type: sint
|
||||
doc: |
|
||||
The FFO (Fractional Frequency Offset) between the RX and TX
|
||||
symbol rate on the media associated with the pin:
|
||||
(rx_frequency-tx_frequency)/rx_frequency
|
||||
The FFO (Fractional Frequency Offset) of the pin.
|
||||
At top level this represents the RX vs TX symbol rate
|
||||
offset on the media associated with the pin. Inside
|
||||
the pin-parent-device nest it represents the frequency
|
||||
offset between the pin and its parent DPLL device.
|
||||
Value is in PPM (parts per million).
|
||||
This may be implemented for example for pin of type
|
||||
PIN_TYPE_SYNCE_ETH_PORT.
|
||||
This is a lower-precision version of
|
||||
fractional-frequency-offset-ppt.
|
||||
-
|
||||
name: esync-frequency
|
||||
type: u64
|
||||
@ -450,12 +494,33 @@ attribute-sets:
|
||||
name: fractional-frequency-offset-ppt
|
||||
type: sint
|
||||
doc: |
|
||||
The FFO (Fractional Frequency Offset) of the pin with respect to
|
||||
the nominal frequency.
|
||||
Value = (frequency_measured - frequency_nominal) / frequency_nominal
|
||||
The FFO (Fractional Frequency Offset) of the pin.
|
||||
At top level this represents the RX vs TX symbol rate
|
||||
offset on the media associated with the pin. Inside
|
||||
the pin-parent-device nest it represents the frequency
|
||||
offset between the pin and its parent DPLL device.
|
||||
Value is in PPT (parts per trillion, 10^-12).
|
||||
Note: This attribute provides higher resolution than the standard
|
||||
fractional-frequency-offset (which is in PPM).
|
||||
This is a higher-precision version of
|
||||
fractional-frequency-offset.
|
||||
-
|
||||
name: measured-frequency
|
||||
type: u64
|
||||
doc: |
|
||||
The measured frequency of the input pin in millihertz (mHz).
|
||||
Value of (DPLL_A_PIN_MEASURED_FREQUENCY /
|
||||
DPLL_PIN_MEASURED_FREQUENCY_DIVIDER) is an integer part (Hz)
|
||||
of a measured frequency value.
|
||||
Value of (DPLL_A_PIN_MEASURED_FREQUENCY %
|
||||
DPLL_PIN_MEASURED_FREQUENCY_DIVIDER) is a fractional part
|
||||
of a measured frequency value.
|
||||
-
|
||||
name: operstate
|
||||
type: u32
|
||||
enum: pin-operstate
|
||||
doc: |
|
||||
Operational state of the pin with respect to its parent DPLL
|
||||
device. Unlike state (which reflects the administrative intent),
|
||||
operstate reflects the actual hardware status.
|
||||
|
||||
-
|
||||
name: pin-parent-device
|
||||
@ -469,8 +534,14 @@ attribute-sets:
|
||||
name: prio
|
||||
-
|
||||
name: state
|
||||
-
|
||||
name: operstate
|
||||
-
|
||||
name: phase-offset
|
||||
-
|
||||
name: fractional-frequency-offset
|
||||
-
|
||||
name: fractional-frequency-offset-ppt
|
||||
-
|
||||
name: pin-parent-pin
|
||||
subset-of: pin
|
||||
@ -544,6 +615,7 @@ operations:
|
||||
- type
|
||||
- phase-offset-monitor
|
||||
- phase-offset-avg-factor
|
||||
- frequency-monitor
|
||||
|
||||
dump:
|
||||
reply: *dev-attrs
|
||||
@ -563,6 +635,7 @@ operations:
|
||||
- mode
|
||||
- phase-offset-monitor
|
||||
- phase-offset-avg-factor
|
||||
- frequency-monitor
|
||||
-
|
||||
name: device-create-ntf
|
||||
doc: Notification about device appearing
|
||||
@ -643,6 +716,7 @@ operations:
|
||||
- esync-frequency-supported
|
||||
- esync-pulse
|
||||
- reference-sync
|
||||
- measured-frequency
|
||||
|
||||
dump:
|
||||
request:
|
||||
|
||||
@ -111,6 +111,7 @@ vmlinux-objs-$(CONFIG_EFI_SBAT) += $(obj)/sbat.o
|
||||
|
||||
ifdef CONFIG_EFI_SBAT
|
||||
$(obj)/sbat.o: $(CONFIG_EFI_SBAT_FILE)
|
||||
AFLAGS_sbat.o += -I $(srctree)
|
||||
endif
|
||||
|
||||
$(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE
|
||||
|
||||
@ -3040,12 +3040,6 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
|
||||
bool prefetch = !fault || fault->prefetch;
|
||||
bool write_fault = fault && fault->write;
|
||||
|
||||
if (unlikely(is_noslot_pfn(pfn))) {
|
||||
vcpu->stat.pf_mmio_spte_created++;
|
||||
mark_mmio_spte(vcpu, sptep, gfn, pte_access);
|
||||
return RET_PF_EMULATE;
|
||||
}
|
||||
|
||||
if (is_shadow_present_pte(*sptep)) {
|
||||
if (prefetch && is_last_spte(*sptep, level) &&
|
||||
pfn == spte_to_pfn(*sptep))
|
||||
@ -3062,13 +3056,22 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
|
||||
child = spte_to_child_sp(pte);
|
||||
drop_parent_pte(vcpu->kvm, child, sptep);
|
||||
flush = true;
|
||||
} else if (WARN_ON_ONCE(pfn != spte_to_pfn(*sptep))) {
|
||||
} else if (pfn != spte_to_pfn(*sptep)) {
|
||||
WARN_ON_ONCE(vcpu->arch.mmu->root_role.direct);
|
||||
drop_spte(vcpu->kvm, sptep);
|
||||
flush = true;
|
||||
} else
|
||||
was_rmapped = 1;
|
||||
}
|
||||
|
||||
if (unlikely(is_noslot_pfn(pfn))) {
|
||||
vcpu->stat.pf_mmio_spte_created++;
|
||||
mark_mmio_spte(vcpu, sptep, gfn, pte_access);
|
||||
if (flush)
|
||||
kvm_flush_remote_tlbs_gfn(vcpu->kvm, gfn, level);
|
||||
return RET_PF_EMULATE;
|
||||
}
|
||||
|
||||
wrprot = make_spte(vcpu, sp, slot, pte_access, gfn, pfn, *sptep, prefetch,
|
||||
false, host_writable, &spte);
|
||||
|
||||
|
||||
@ -2970,7 +2970,7 @@ CONFIG_AMD_XGBE=m
|
||||
CONFIG_NET_XGENE=m
|
||||
CONFIG_NET_XGENE_V2=m
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_SPI_AX88796C is not set
|
||||
|
||||
@ -2965,7 +2965,7 @@ CONFIG_AMD_XGBE=m
|
||||
CONFIG_NET_XGENE=m
|
||||
CONFIG_NET_XGENE_V2=m
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_SPI_AX88796C is not set
|
||||
|
||||
@ -2973,7 +2973,7 @@ CONFIG_AMD_XGBE=m
|
||||
CONFIG_NET_XGENE=m
|
||||
CONFIG_NET_XGENE_V2=m
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_SPI_AX88796C is not set
|
||||
|
||||
@ -2957,7 +2957,7 @@ CONFIG_AMD_XGBE=m
|
||||
CONFIG_NET_XGENE=m
|
||||
CONFIG_NET_XGENE_V2=m
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_SPI_AX88796C is not set
|
||||
|
||||
@ -2952,7 +2952,7 @@ CONFIG_AMD_XGBE=m
|
||||
CONFIG_NET_XGENE=m
|
||||
CONFIG_NET_XGENE_V2=m
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_SPI_AX88796C is not set
|
||||
|
||||
@ -2959,7 +2959,7 @@ CONFIG_AMD_XGBE=m
|
||||
CONFIG_NET_XGENE=m
|
||||
CONFIG_NET_XGENE_V2=m
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_SPI_AX88796C is not set
|
||||
|
||||
@ -2954,7 +2954,7 @@ CONFIG_AMD_XGBE=m
|
||||
CONFIG_NET_XGENE=m
|
||||
CONFIG_NET_XGENE_V2=m
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_SPI_AX88796C is not set
|
||||
|
||||
@ -2968,7 +2968,7 @@ CONFIG_AMD_XGBE=m
|
||||
CONFIG_NET_XGENE=m
|
||||
CONFIG_NET_XGENE_V2=m
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_SPI_AX88796C is not set
|
||||
|
||||
@ -2559,7 +2559,7 @@ CONFIG_NET_VENDOR_AMAZON=y
|
||||
# CONFIG_ENA_ETHERNET is not set
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
CONFIG_NET_VENDOR_ATHEROS=y
|
||||
|
||||
@ -2561,7 +2561,7 @@ CONFIG_NET_VENDOR_AMAZON=y
|
||||
# CONFIG_ENA_ETHERNET is not set
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
CONFIG_NET_VENDOR_ATHEROS=y
|
||||
|
||||
@ -2599,7 +2599,7 @@ CONFIG_NET_VENDOR_AMAZON=y
|
||||
# CONFIG_ENA_ETHERNET is not set
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
CONFIG_NET_VENDOR_ATHEROS=y
|
||||
|
||||
@ -2595,7 +2595,7 @@ CONFIG_NET_VENDOR_AMAZON=y
|
||||
# CONFIG_ENA_ETHERNET is not set
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
CONFIG_NET_VENDOR_ATHEROS=y
|
||||
|
||||
@ -2022,7 +2022,7 @@ CONFIG_ETHERNET=y
|
||||
CONFIG_NET_VENDOR_AMAZON=y
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||
|
||||
@ -2046,7 +2046,7 @@ CONFIG_ETHERNET=y
|
||||
CONFIG_NET_VENDOR_AMAZON=y
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
CONFIG_NET_VENDOR_AQUANTIA=y
|
||||
# CONFIG_AQTION is not set
|
||||
CONFIG_AQTION=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ASIX=y
|
||||
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||
|
||||
@ -228,6 +228,7 @@ config CRYPTO_AUTHENC
|
||||
select CRYPTO_SKCIPHER
|
||||
select CRYPTO_MANAGER
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_NULL
|
||||
help
|
||||
Authenc: Combined mode wrapper for IPsec.
|
||||
|
||||
@ -1438,6 +1439,7 @@ config CRYPTO_USER_API_AEAD
|
||||
depends on NET
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_SKCIPHER
|
||||
select CRYPTO_NULL
|
||||
select CRYPTO_USER_API
|
||||
help
|
||||
Enable the userspace interface for AEAD cipher algorithms.
|
||||
|
||||
@ -623,8 +623,10 @@ static int af_alg_alloc_tsgl(struct sock *sk)
|
||||
sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
|
||||
sgl->cur = 0;
|
||||
|
||||
if (sg)
|
||||
if (sg) {
|
||||
sg_unmark_end(sg + MAX_SGL_ENTS - 1);
|
||||
sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
|
||||
}
|
||||
|
||||
list_add_tail(&sgl->list, &ctx->tsgl_list);
|
||||
}
|
||||
@ -1220,6 +1222,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
|
||||
|
||||
seglen = min_t(size_t, (maxsize - len),
|
||||
msg_data_left(msg));
|
||||
/* Never pin more pages than the remaining RX accounting budget. */
|
||||
seglen = min_t(size_t, seglen, af_alg_rcvbuf(sk));
|
||||
|
||||
if (list_empty(&areq->rsgl_list)) {
|
||||
rsgl = &areq->first_rsgl;
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#include <crypto/internal/aead.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/if_alg.h>
|
||||
#include <crypto/skcipher.h>
|
||||
#include <crypto/null.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -34,13 +36,19 @@
|
||||
#include <linux/net.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
struct aead_tfm {
|
||||
struct crypto_aead *aead;
|
||||
struct crypto_sync_skcipher *null_tfm;
|
||||
};
|
||||
|
||||
static inline bool aead_sufficient_data(struct sock *sk)
|
||||
{
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct sock *psk = ask->parent;
|
||||
struct alg_sock *pask = alg_sk(psk);
|
||||
struct af_alg_ctx *ctx = ask->private;
|
||||
struct crypto_aead *tfm = pask->private;
|
||||
struct aead_tfm *aeadc = pask->private;
|
||||
struct crypto_aead *tfm = aeadc->aead;
|
||||
unsigned int as = crypto_aead_authsize(tfm);
|
||||
|
||||
/*
|
||||
@ -56,12 +64,27 @@ static int aead_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct sock *psk = ask->parent;
|
||||
struct alg_sock *pask = alg_sk(psk);
|
||||
struct crypto_aead *tfm = pask->private;
|
||||
struct aead_tfm *aeadc = pask->private;
|
||||
struct crypto_aead *tfm = aeadc->aead;
|
||||
unsigned int ivsize = crypto_aead_ivsize(tfm);
|
||||
|
||||
return af_alg_sendmsg(sock, msg, size, ivsize);
|
||||
}
|
||||
|
||||
static int crypto_aead_copy_sgl(struct crypto_sync_skcipher *null_tfm,
|
||||
struct scatterlist *src,
|
||||
struct scatterlist *dst, unsigned int len)
|
||||
{
|
||||
SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, null_tfm);
|
||||
|
||||
skcipher_request_set_sync_tfm(skreq, null_tfm);
|
||||
skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_SLEEP,
|
||||
NULL, NULL);
|
||||
skcipher_request_set_crypt(skreq, src, dst, len, NULL);
|
||||
|
||||
return crypto_skcipher_encrypt(skreq);
|
||||
}
|
||||
|
||||
static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||
size_t ignored, int flags)
|
||||
{
|
||||
@ -70,7 +93,9 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||
struct sock *psk = ask->parent;
|
||||
struct alg_sock *pask = alg_sk(psk);
|
||||
struct af_alg_ctx *ctx = ask->private;
|
||||
struct crypto_aead *tfm = pask->private;
|
||||
struct aead_tfm *aeadc = pask->private;
|
||||
struct crypto_aead *tfm = aeadc->aead;
|
||||
struct crypto_sync_skcipher *null_tfm = aeadc->null_tfm;
|
||||
unsigned int as = crypto_aead_authsize(tfm);
|
||||
unsigned int ivsize = crypto_aead_ivsize(tfm);
|
||||
struct af_alg_async_req *areq;
|
||||
@ -150,7 +175,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||
if (usedpages < outlen) {
|
||||
size_t less = outlen - usedpages;
|
||||
|
||||
if (used < less) {
|
||||
if (used < less + (ctx->enc ? 0 : as)) {
|
||||
err = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
@ -189,7 +214,10 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||
/* Use the RX SGL as source (and destination) for crypto op. */
|
||||
rsgl_src = areq->first_rsgl.sgl.sgt.sgl;
|
||||
|
||||
memcpy_sglist(rsgl_src, tsgl_src, ctx->aead_assoclen);
|
||||
err = crypto_aead_copy_sgl(null_tfm, tsgl_src, rsgl_src,
|
||||
ctx->aead_assoclen);
|
||||
if (err)
|
||||
goto free;
|
||||
|
||||
/* Initialize the crypto operation */
|
||||
aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
|
||||
@ -292,7 +320,7 @@ static int aead_check_key(struct socket *sock)
|
||||
int err = 0;
|
||||
struct sock *psk;
|
||||
struct alg_sock *pask;
|
||||
struct crypto_aead *tfm;
|
||||
struct aead_tfm *tfm;
|
||||
struct sock *sk = sock->sk;
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
|
||||
@ -306,7 +334,7 @@ static int aead_check_key(struct socket *sock)
|
||||
|
||||
err = -ENOKEY;
|
||||
lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
|
||||
if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
|
||||
if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY)
|
||||
goto unlock;
|
||||
|
||||
atomic_dec(&pask->nokey_refcnt);
|
||||
@ -367,22 +395,54 @@ static struct proto_ops algif_aead_ops_nokey = {
|
||||
|
||||
static void *aead_bind(const char *name, u32 type, u32 mask)
|
||||
{
|
||||
return crypto_alloc_aead(name, type, mask);
|
||||
struct aead_tfm *tfm;
|
||||
struct crypto_aead *aead;
|
||||
struct crypto_sync_skcipher *null_tfm;
|
||||
|
||||
tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
|
||||
if (!tfm)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
aead = crypto_alloc_aead(name, type, mask);
|
||||
if (IS_ERR(aead)) {
|
||||
kfree(tfm);
|
||||
return ERR_CAST(aead);
|
||||
}
|
||||
|
||||
null_tfm = crypto_get_default_null_skcipher();
|
||||
if (IS_ERR(null_tfm)) {
|
||||
crypto_free_aead(aead);
|
||||
kfree(tfm);
|
||||
return ERR_CAST(null_tfm);
|
||||
}
|
||||
|
||||
tfm->aead = aead;
|
||||
tfm->null_tfm = null_tfm;
|
||||
|
||||
return tfm;
|
||||
}
|
||||
|
||||
static void aead_release(void *private)
|
||||
{
|
||||
crypto_free_aead(private);
|
||||
struct aead_tfm *tfm = private;
|
||||
|
||||
crypto_free_aead(tfm->aead);
|
||||
crypto_put_default_null_skcipher();
|
||||
kfree(tfm);
|
||||
}
|
||||
|
||||
static int aead_setauthsize(void *private, unsigned int authsize)
|
||||
{
|
||||
return crypto_aead_setauthsize(private, authsize);
|
||||
struct aead_tfm *tfm = private;
|
||||
|
||||
return crypto_aead_setauthsize(tfm->aead, authsize);
|
||||
}
|
||||
|
||||
static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
|
||||
{
|
||||
return crypto_aead_setkey(private, key, keylen);
|
||||
struct aead_tfm *tfm = private;
|
||||
|
||||
return crypto_aead_setkey(tfm->aead, key, keylen);
|
||||
}
|
||||
|
||||
static void aead_sock_destruct(struct sock *sk)
|
||||
@ -391,7 +451,8 @@ static void aead_sock_destruct(struct sock *sk)
|
||||
struct af_alg_ctx *ctx = ask->private;
|
||||
struct sock *psk = ask->parent;
|
||||
struct alg_sock *pask = alg_sk(psk);
|
||||
struct crypto_aead *tfm = pask->private;
|
||||
struct aead_tfm *aeadc = pask->private;
|
||||
struct crypto_aead *tfm = aeadc->aead;
|
||||
unsigned int ivlen = crypto_aead_ivsize(tfm);
|
||||
|
||||
af_alg_pull_tsgl(sk, ctx->used, NULL);
|
||||
@ -404,9 +465,10 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk)
|
||||
{
|
||||
struct af_alg_ctx *ctx;
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct crypto_aead *tfm = private;
|
||||
struct aead_tfm *tfm = private;
|
||||
struct crypto_aead *aead = tfm->aead;
|
||||
unsigned int len = sizeof(*ctx);
|
||||
unsigned int ivlen = crypto_aead_ivsize(tfm);
|
||||
unsigned int ivlen = crypto_aead_ivsize(aead);
|
||||
|
||||
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
|
||||
if (!ctx)
|
||||
@ -433,9 +495,9 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk)
|
||||
|
||||
static int aead_accept_parent(void *private, struct sock *sk)
|
||||
{
|
||||
struct crypto_aead *tfm = private;
|
||||
struct aead_tfm *tfm = private;
|
||||
|
||||
if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
|
||||
if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY)
|
||||
return -ENOKEY;
|
||||
|
||||
return aead_accept_parent_nokey(private, sk);
|
||||
|
||||
@ -130,6 +130,11 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||
* full block size buffers.
|
||||
*/
|
||||
if (ctx->more || len < ctx->used) {
|
||||
if (len < bs) {
|
||||
err = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
|
||||
len -= len % bs;
|
||||
cflags |= CRYPTO_SKCIPHER_REQ_NOTFINAL;
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <crypto/public_key.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <keys/system_keyring.h>
|
||||
@ -151,12 +152,17 @@ struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
|
||||
size_t len_2)
|
||||
{
|
||||
struct asymmetric_key_id *kid;
|
||||
size_t kid_sz;
|
||||
size_t len;
|
||||
|
||||
kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2,
|
||||
GFP_KERNEL);
|
||||
if (check_add_overflow(len_1, len_2, &len))
|
||||
return ERR_PTR(-EOVERFLOW);
|
||||
if (check_add_overflow(sizeof(struct asymmetric_key_id), len, &kid_sz))
|
||||
return ERR_PTR(-EOVERFLOW);
|
||||
kid = kmalloc(kid_sz, GFP_KERNEL);
|
||||
if (!kid)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
kid->len = len_1 + len_2;
|
||||
kid->len = len;
|
||||
memcpy(kid->data, val_1, len_1);
|
||||
memcpy(kid->data + len_1, val_2, len_2);
|
||||
return kid;
|
||||
|
||||
107
crypto/authenc.c
107
crypto/authenc.c
@ -9,6 +9,7 @@
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/authenc.h>
|
||||
#include <crypto/null.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
@ -27,6 +28,7 @@ struct authenc_instance_ctx {
|
||||
struct crypto_authenc_ctx {
|
||||
struct crypto_ahash *auth;
|
||||
struct crypto_skcipher *enc;
|
||||
struct crypto_sync_skcipher *null;
|
||||
};
|
||||
|
||||
struct authenc_request_ctx {
|
||||
@ -37,7 +39,7 @@ struct authenc_request_ctx {
|
||||
|
||||
static void authenc_request_complete(struct aead_request *req, int err)
|
||||
{
|
||||
if (err != -EINPROGRESS)
|
||||
if (err != -EINPROGRESS && err != -EBUSY)
|
||||
aead_request_complete(req, err);
|
||||
}
|
||||
|
||||
@ -107,27 +109,42 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void authenc_geniv_ahash_done(void *data, int err)
|
||||
static void authenc_geniv_ahash_finish(struct aead_request *req)
|
||||
{
|
||||
struct aead_request *req = data;
|
||||
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
|
||||
struct aead_instance *inst = aead_alg_instance(authenc);
|
||||
struct authenc_instance_ctx *ictx = aead_instance_ctx(inst);
|
||||
struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
|
||||
struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
scatterwalk_map_and_copy(ahreq->result, req->dst,
|
||||
req->assoclen + req->cryptlen,
|
||||
crypto_aead_authsize(authenc), 1);
|
||||
}
|
||||
|
||||
out:
|
||||
static void authenc_geniv_ahash_done(void *data, int err)
|
||||
{
|
||||
struct aead_request *req = data;
|
||||
|
||||
if (!err)
|
||||
authenc_geniv_ahash_finish(req);
|
||||
aead_request_complete(req, err);
|
||||
}
|
||||
|
||||
static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
|
||||
/*
|
||||
* Used when the ahash request was invoked in the async callback context
|
||||
* of the previous skcipher request. Eat any EINPROGRESS notifications.
|
||||
*/
|
||||
static void authenc_geniv_ahash_done2(void *data, int err)
|
||||
{
|
||||
struct aead_request *req = data;
|
||||
|
||||
if (!err)
|
||||
authenc_geniv_ahash_finish(req);
|
||||
authenc_request_complete(req, err);
|
||||
}
|
||||
|
||||
static int crypto_authenc_genicv(struct aead_request *req, unsigned int mask)
|
||||
{
|
||||
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
|
||||
struct aead_instance *inst = aead_alg_instance(authenc);
|
||||
@ -136,6 +153,7 @@ static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
|
||||
struct crypto_ahash *auth = ctx->auth;
|
||||
struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
|
||||
struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
|
||||
unsigned int flags = aead_request_flags(req) & ~mask;
|
||||
u8 *hash = areq_ctx->tail;
|
||||
int err;
|
||||
|
||||
@ -143,7 +161,8 @@ static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
|
||||
ahash_request_set_crypt(ahreq, req->dst, hash,
|
||||
req->assoclen + req->cryptlen);
|
||||
ahash_request_set_callback(ahreq, flags,
|
||||
authenc_geniv_ahash_done, req);
|
||||
mask ? authenc_geniv_ahash_done2 :
|
||||
authenc_geniv_ahash_done, req);
|
||||
|
||||
err = crypto_ahash_digest(ahreq);
|
||||
if (err)
|
||||
@ -159,15 +178,29 @@ static void crypto_authenc_encrypt_done(void *data, int err)
|
||||
{
|
||||
struct aead_request *areq = data;
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = crypto_authenc_genicv(areq, 0);
|
||||
|
||||
out:
|
||||
if (err) {
|
||||
aead_request_complete(areq, err);
|
||||
return;
|
||||
}
|
||||
err = crypto_authenc_genicv(areq, CRYPTO_TFM_REQ_MAY_SLEEP);
|
||||
authenc_request_complete(areq, err);
|
||||
}
|
||||
|
||||
static int crypto_authenc_copy_assoc(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
|
||||
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
|
||||
SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null);
|
||||
|
||||
skcipher_request_set_sync_tfm(skreq, ctx->null);
|
||||
skcipher_request_set_callback(skreq, aead_request_flags(req),
|
||||
NULL, NULL);
|
||||
skcipher_request_set_crypt(skreq, req->src, req->dst, req->assoclen,
|
||||
NULL);
|
||||
|
||||
return crypto_skcipher_encrypt(skreq);
|
||||
}
|
||||
|
||||
static int crypto_authenc_encrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
|
||||
@ -186,7 +219,10 @@ static int crypto_authenc_encrypt(struct aead_request *req)
|
||||
dst = src;
|
||||
|
||||
if (req->src != req->dst) {
|
||||
memcpy_sglist(req->dst, req->src, req->assoclen);
|
||||
err = crypto_authenc_copy_assoc(req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, req->assoclen);
|
||||
}
|
||||
|
||||
@ -199,11 +235,18 @@ static int crypto_authenc_encrypt(struct aead_request *req)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return crypto_authenc_genicv(req, aead_request_flags(req));
|
||||
return crypto_authenc_genicv(req, 0);
|
||||
}
|
||||
|
||||
static void authenc_decrypt_tail_done(void *data, int err)
|
||||
{
|
||||
struct aead_request *req = data;
|
||||
|
||||
authenc_request_complete(req, err);
|
||||
}
|
||||
|
||||
static int crypto_authenc_decrypt_tail(struct aead_request *req,
|
||||
unsigned int flags)
|
||||
unsigned int mask)
|
||||
{
|
||||
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
|
||||
struct aead_instance *inst = aead_alg_instance(authenc);
|
||||
@ -214,6 +257,7 @@ static int crypto_authenc_decrypt_tail(struct aead_request *req,
|
||||
struct skcipher_request *skreq = (void *)(areq_ctx->tail +
|
||||
ictx->reqoff);
|
||||
unsigned int authsize = crypto_aead_authsize(authenc);
|
||||
unsigned int flags = aead_request_flags(req) & ~mask;
|
||||
u8 *ihash = ahreq->result + authsize;
|
||||
struct scatterlist *src, *dst;
|
||||
|
||||
@ -230,7 +274,9 @@ static int crypto_authenc_decrypt_tail(struct aead_request *req,
|
||||
|
||||
skcipher_request_set_tfm(skreq, ctx->enc);
|
||||
skcipher_request_set_callback(skreq, flags,
|
||||
req->base.complete, req->base.data);
|
||||
mask ? authenc_decrypt_tail_done :
|
||||
req->base.complete,
|
||||
mask ? req : req->base.data);
|
||||
skcipher_request_set_crypt(skreq, src, dst,
|
||||
req->cryptlen - authsize, req->iv);
|
||||
|
||||
@ -241,12 +287,11 @@ static void authenc_verify_ahash_done(void *data, int err)
|
||||
{
|
||||
struct aead_request *req = data;
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = crypto_authenc_decrypt_tail(req, 0);
|
||||
|
||||
out:
|
||||
if (err) {
|
||||
aead_request_complete(req, err);
|
||||
return;
|
||||
}
|
||||
err = crypto_authenc_decrypt_tail(req, CRYPTO_TFM_REQ_MAY_SLEEP);
|
||||
authenc_request_complete(req, err);
|
||||
}
|
||||
|
||||
@ -273,7 +318,7 @@ static int crypto_authenc_decrypt(struct aead_request *req)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return crypto_authenc_decrypt_tail(req, aead_request_flags(req));
|
||||
return crypto_authenc_decrypt_tail(req, 0);
|
||||
}
|
||||
|
||||
static int crypto_authenc_init_tfm(struct crypto_aead *tfm)
|
||||
@ -283,6 +328,7 @@ static int crypto_authenc_init_tfm(struct crypto_aead *tfm)
|
||||
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(tfm);
|
||||
struct crypto_ahash *auth;
|
||||
struct crypto_skcipher *enc;
|
||||
struct crypto_sync_skcipher *null;
|
||||
int err;
|
||||
|
||||
auth = crypto_spawn_ahash(&ictx->auth);
|
||||
@ -294,8 +340,14 @@ static int crypto_authenc_init_tfm(struct crypto_aead *tfm)
|
||||
if (IS_ERR(enc))
|
||||
goto err_free_ahash;
|
||||
|
||||
null = crypto_get_default_null_skcipher();
|
||||
err = PTR_ERR(null);
|
||||
if (IS_ERR(null))
|
||||
goto err_free_skcipher;
|
||||
|
||||
ctx->auth = auth;
|
||||
ctx->enc = enc;
|
||||
ctx->null = null;
|
||||
|
||||
crypto_aead_set_reqsize(
|
||||
tfm,
|
||||
@ -309,6 +361,8 @@ static int crypto_authenc_init_tfm(struct crypto_aead *tfm)
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_skcipher:
|
||||
crypto_free_skcipher(enc);
|
||||
err_free_ahash:
|
||||
crypto_free_ahash(auth);
|
||||
return err;
|
||||
@ -320,6 +374,7 @@ static void crypto_authenc_exit_tfm(struct crypto_aead *tfm)
|
||||
|
||||
crypto_free_ahash(ctx->auth);
|
||||
crypto_free_skcipher(ctx->enc);
|
||||
crypto_put_default_null_skcipher();
|
||||
}
|
||||
|
||||
static void crypto_authenc_free(struct aead_instance *inst)
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/authenc.h>
|
||||
#include <crypto/null.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
@ -30,6 +31,7 @@ struct crypto_authenc_esn_ctx {
|
||||
unsigned int reqoff;
|
||||
struct crypto_ahash *auth;
|
||||
struct crypto_skcipher *enc;
|
||||
struct crypto_sync_skcipher *null;
|
||||
};
|
||||
|
||||
struct authenc_esn_request_ctx {
|
||||
@ -156,6 +158,28 @@ static void crypto_authenc_esn_encrypt_done(void *data, int err)
|
||||
authenc_esn_request_complete(areq, err);
|
||||
}
|
||||
|
||||
static int crypto_authenc_esn_copy_sg(struct aead_request *req,
|
||||
struct scatterlist *src,
|
||||
struct scatterlist *dst,
|
||||
unsigned int len)
|
||||
{
|
||||
struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
|
||||
struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
|
||||
SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null);
|
||||
|
||||
skcipher_request_set_sync_tfm(skreq, ctx->null);
|
||||
skcipher_request_set_callback(skreq, aead_request_flags(req),
|
||||
NULL, NULL);
|
||||
skcipher_request_set_crypt(skreq, src, dst, len, NULL);
|
||||
|
||||
return crypto_skcipher_encrypt(skreq);
|
||||
}
|
||||
|
||||
static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len)
|
||||
{
|
||||
return crypto_authenc_esn_copy_sg(req, req->src, req->dst, len);
|
||||
}
|
||||
|
||||
static int crypto_authenc_esn_encrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
|
||||
@ -177,7 +201,10 @@ static int crypto_authenc_esn_encrypt(struct aead_request *req)
|
||||
dst = src;
|
||||
|
||||
if (req->src != req->dst) {
|
||||
memcpy_sglist(req->dst, req->src, assoclen);
|
||||
err = crypto_authenc_esn_copy(req, assoclen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sg_init_table(areq_ctx->dst, 2);
|
||||
dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, assoclen);
|
||||
}
|
||||
@ -211,6 +238,7 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
|
||||
struct scatterlist *dst = req->dst;
|
||||
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
|
||||
u32 tmp[2];
|
||||
int err;
|
||||
|
||||
if (!authsize)
|
||||
goto decrypt;
|
||||
@ -220,8 +248,11 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
|
||||
scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
|
||||
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
|
||||
scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
|
||||
} else
|
||||
memcpy_sglist(dst, src, assoclen);
|
||||
} else {
|
||||
err = crypto_authenc_esn_copy(req, assoclen);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (crypto_memneq(ihash, ohash, authsize))
|
||||
return -EBADMSG;
|
||||
@ -289,7 +320,10 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
|
||||
|
||||
src = scatterwalk_ffwd(areq_ctx->src, src, 8);
|
||||
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
|
||||
memcpy_sglist(dst, src, assoclen + cryptlen - 8);
|
||||
err = crypto_authenc_esn_copy_sg(req, src, dst,
|
||||
assoclen + cryptlen - 8);
|
||||
if (err)
|
||||
return err;
|
||||
dst = req->dst;
|
||||
}
|
||||
|
||||
@ -313,6 +347,7 @@ static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm)
|
||||
struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm);
|
||||
struct crypto_ahash *auth;
|
||||
struct crypto_skcipher *enc;
|
||||
struct crypto_sync_skcipher *null;
|
||||
int err;
|
||||
|
||||
auth = crypto_spawn_ahash(&ictx->auth);
|
||||
@ -324,8 +359,14 @@ static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm)
|
||||
if (IS_ERR(enc))
|
||||
goto err_free_ahash;
|
||||
|
||||
null = crypto_get_default_null_skcipher();
|
||||
err = PTR_ERR(null);
|
||||
if (IS_ERR(null))
|
||||
goto err_free_skcipher;
|
||||
|
||||
ctx->auth = auth;
|
||||
ctx->enc = enc;
|
||||
ctx->null = null;
|
||||
|
||||
ctx->reqoff = 2 * crypto_ahash_digestsize(auth);
|
||||
|
||||
@ -341,6 +382,8 @@ static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm)
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_skcipher:
|
||||
crypto_free_skcipher(enc);
|
||||
err_free_ahash:
|
||||
crypto_free_ahash(auth);
|
||||
return err;
|
||||
@ -352,6 +395,7 @@ static void crypto_authenc_esn_exit_tfm(struct crypto_aead *tfm)
|
||||
|
||||
crypto_free_ahash(ctx->auth);
|
||||
crypto_free_skcipher(ctx->enc);
|
||||
crypto_put_default_null_skcipher();
|
||||
}
|
||||
|
||||
static void crypto_authenc_esn_free(struct aead_instance *inst)
|
||||
@ -390,6 +434,11 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl,
|
||||
auth = crypto_spawn_ahash_alg(&ctx->auth);
|
||||
auth_base = &auth->base;
|
||||
|
||||
if (auth->digestsize > 0 && auth->digestsize < 4) {
|
||||
err = -EINVAL;
|
||||
goto err_free_inst;
|
||||
}
|
||||
|
||||
err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst),
|
||||
crypto_attr_alg_name(tb[2]), 0, mask);
|
||||
if (err)
|
||||
|
||||
@ -69,100 +69,6 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy);
|
||||
|
||||
/**
|
||||
* memcpy_sglist() - Copy data from one scatterlist to another
|
||||
* @dst: The destination scatterlist. Can be NULL if @nbytes == 0.
|
||||
* @src: The source scatterlist. Can be NULL if @nbytes == 0.
|
||||
* @nbytes: Number of bytes to copy
|
||||
*
|
||||
* The scatterlists can describe exactly the same memory, in which case this
|
||||
* function is a no-op. No other overlaps are supported.
|
||||
*
|
||||
* Context: Any context
|
||||
*/
|
||||
void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
unsigned int src_offset, dst_offset;
|
||||
|
||||
if (unlikely(nbytes == 0)) /* in case src and/or dst is NULL */
|
||||
return;
|
||||
|
||||
src_offset = src->offset;
|
||||
dst_offset = dst->offset;
|
||||
for (;;) {
|
||||
/* Compute the length to copy this step. */
|
||||
unsigned int len = min3(src->offset + src->length - src_offset,
|
||||
dst->offset + dst->length - dst_offset,
|
||||
nbytes);
|
||||
struct page *src_page = sg_page(src);
|
||||
struct page *dst_page = sg_page(dst);
|
||||
const void *src_virt;
|
||||
void *dst_virt;
|
||||
|
||||
if (IS_ENABLED(CONFIG_HIGHMEM)) {
|
||||
/* HIGHMEM: we may have to actually map the pages. */
|
||||
const unsigned int src_oip = offset_in_page(src_offset);
|
||||
const unsigned int dst_oip = offset_in_page(dst_offset);
|
||||
const unsigned int limit = PAGE_SIZE;
|
||||
|
||||
/* Further limit len to not cross a page boundary. */
|
||||
len = min3(len, limit - src_oip, limit - dst_oip);
|
||||
|
||||
/* Compute the source and destination pages. */
|
||||
src_page += src_offset / PAGE_SIZE;
|
||||
dst_page += dst_offset / PAGE_SIZE;
|
||||
|
||||
if (src_page != dst_page) {
|
||||
/* Copy between different pages. */
|
||||
memcpy_page(dst_page, dst_oip,
|
||||
src_page, src_oip, len);
|
||||
flush_dcache_page(dst_page);
|
||||
} else if (src_oip != dst_oip) {
|
||||
/* Copy between different parts of same page. */
|
||||
dst_virt = kmap_local_page(dst_page);
|
||||
memcpy(dst_virt + dst_oip, dst_virt + src_oip,
|
||||
len);
|
||||
kunmap_local(dst_virt);
|
||||
flush_dcache_page(dst_page);
|
||||
} /* Else, it's the same memory. No action needed. */
|
||||
} else {
|
||||
/*
|
||||
* !HIGHMEM: no mapping needed. Just work in the linear
|
||||
* buffer of each sg entry. Note that we can cross page
|
||||
* boundaries, as they are not significant in this case.
|
||||
*/
|
||||
src_virt = page_address(src_page) + src_offset;
|
||||
dst_virt = page_address(dst_page) + dst_offset;
|
||||
if (src_virt != dst_virt) {
|
||||
memcpy(dst_virt, src_virt, len);
|
||||
if (ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE)
|
||||
__scatterwalk_flush_dcache_pages(
|
||||
dst_page, dst_offset, len);
|
||||
} /* Else, it's the same memory. No action needed. */
|
||||
}
|
||||
nbytes -= len;
|
||||
if (nbytes == 0) /* No more to copy? */
|
||||
break;
|
||||
|
||||
/*
|
||||
* There's more to copy. Advance the offsets by the length
|
||||
* copied this step, and advance the sg entries as needed.
|
||||
*/
|
||||
src_offset += len;
|
||||
if (src_offset >= src->offset + src->length) {
|
||||
src = sg_next(src);
|
||||
src_offset = src->offset;
|
||||
}
|
||||
dst_offset += len;
|
||||
if (dst_offset >= dst->offset + dst->length) {
|
||||
dst = sg_next(dst);
|
||||
dst_offset = dst->offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(memcpy_sglist);
|
||||
|
||||
struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
|
||||
struct scatterlist *src,
|
||||
unsigned int len)
|
||||
|
||||
@ -2241,12 +2241,13 @@ again:
|
||||
|
||||
ret = nbd_start_device(nbd);
|
||||
out:
|
||||
mutex_unlock(&nbd->config_lock);
|
||||
if (!ret) {
|
||||
set_bit(NBD_RT_HAS_CONFIG_REF, &config->runtime_flags);
|
||||
refcount_inc(&nbd->config_refs);
|
||||
nbd_connect_reply(info, nbd->index);
|
||||
}
|
||||
mutex_unlock(&nbd->config_lock);
|
||||
|
||||
nbd_config_put(nbd);
|
||||
if (put_dev)
|
||||
nbd_put(nbd);
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
* Crypto driver to handle block cipher algorithms using NVIDIA Security Engine.
|
||||
*/
|
||||
|
||||
#include <linux/bottom_half.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
@ -333,7 +334,9 @@ out:
|
||||
tegra_key_invalidate_reserved(ctx->se, key2_id, ctx->alg);
|
||||
|
||||
out_finalize:
|
||||
local_bh_disable();
|
||||
crypto_finalize_skcipher_request(se->engine, req, ret);
|
||||
local_bh_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1261,7 +1264,9 @@ out_free_inbuf:
|
||||
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
|
||||
|
||||
out_finalize:
|
||||
local_bh_disable();
|
||||
crypto_finalize_aead_request(ctx->se->engine, req, ret);
|
||||
local_bh_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1347,7 +1352,9 @@ out_free_inbuf:
|
||||
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
|
||||
|
||||
out_finalize:
|
||||
local_bh_disable();
|
||||
crypto_finalize_aead_request(ctx->se->engine, req, ret);
|
||||
local_bh_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1745,7 +1752,9 @@ out:
|
||||
if (tegra_key_is_reserved(rctx->key_id))
|
||||
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
|
||||
|
||||
local_bh_disable();
|
||||
crypto_finalize_hash_request(se->engine, req, ret);
|
||||
local_bh_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
* Crypto driver to handle HASH algorithms using NVIDIA Security Engine.
|
||||
*/
|
||||
|
||||
#include <linux/bottom_half.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
@ -543,7 +544,9 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
|
||||
}
|
||||
|
||||
out:
|
||||
local_bh_disable();
|
||||
crypto_finalize_hash_request(se->engine, req, ret);
|
||||
local_bh_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -880,7 +880,11 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
|
||||
|
||||
if (WARN_ON(!ops) ||
|
||||
WARN_ON(!ops->state_on_dpll_get) ||
|
||||
WARN_ON(!ops->direction_get))
|
||||
WARN_ON(!ops->direction_get) ||
|
||||
WARN_ON(ops->measured_freq_get &&
|
||||
(!dpll_device_ops(dpll)->freq_monitor_get ||
|
||||
!dpll_device_ops(dpll)->freq_monitor_set)) ||
|
||||
WARN_ON(ops->supported_ffo && !ops->ffo_get))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dpll_lock);
|
||||
|
||||
@ -175,6 +175,26 @@ dpll_msg_add_phase_offset_monitor(struct sk_buff *msg, struct dpll_device *dpll,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dpll_msg_add_freq_monitor(struct sk_buff *msg, struct dpll_device *dpll,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct dpll_device_ops *ops = dpll_device_ops(dpll);
|
||||
enum dpll_feature_state state;
|
||||
int ret;
|
||||
|
||||
if (ops->freq_monitor_set && ops->freq_monitor_get) {
|
||||
ret = ops->freq_monitor_get(dpll, dpll_priv(dpll),
|
||||
&state, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (nla_put_u32(msg, DPLL_A_FREQUENCY_MONITOR, state))
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dpll_msg_add_phase_offset_avg_factor(struct sk_buff *msg,
|
||||
struct dpll_device *dpll,
|
||||
@ -304,6 +324,30 @@ dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dpll_msg_add_pin_operstate(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
struct dpll_pin_ref *ref,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
|
||||
struct dpll_device *dpll = ref->dpll;
|
||||
enum dpll_pin_operstate operstate;
|
||||
int ret;
|
||||
|
||||
if (!ops->operstate_on_dpll_get)
|
||||
return 0;
|
||||
ret = ops->operstate_on_dpll_get(pin,
|
||||
dpll_pin_on_dpll_priv(dpll, pin),
|
||||
dpll, dpll_priv(dpll),
|
||||
&operstate, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (nla_put_u32(msg, DPLL_A_PIN_OPERSTATE, operstate))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
struct dpll_pin_ref *ref,
|
||||
@ -373,31 +417,66 @@ dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
|
||||
static int dpll_msg_add_ffo(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
struct dpll_pin_ref *ref,
|
||||
enum dpll_ffo_type type,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
|
||||
struct dpll_device *dpll = ref->dpll;
|
||||
s64 ffo;
|
||||
struct dpll_ffo_param ffo = { .type = type };
|
||||
int ret;
|
||||
|
||||
if (!ops->ffo_get)
|
||||
/* RHEL: To maintain backward compatibility with older binary modules,
|
||||
* we must accept a value of zero for .supported_ffo when the type is
|
||||
* DPLL_FFO_PORT_RXTX_RATE.
|
||||
*/
|
||||
if (!ops->ffo_get ||
|
||||
!((ops->supported_ffo & BIT(type)) ||
|
||||
(!ops->supported_ffo && type == DPLL_FFO_PORT_RXTX_RATE)))
|
||||
return 0;
|
||||
ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
|
||||
dpll, dpll_priv(dpll), &ffo, extack);
|
||||
ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(ref->dpll, pin),
|
||||
ref->dpll, dpll_priv(ref->dpll), &ffo, extack);
|
||||
if (ret) {
|
||||
if (ret == -ENODATA)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
/* Put the FFO value in PPM to preserve compatibility with older
|
||||
* programs.
|
||||
*/
|
||||
ret = nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET,
|
||||
div_s64(ffo, 1000000));
|
||||
if (ret)
|
||||
if (nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET,
|
||||
div_s64(ffo.ffo, 1000000)))
|
||||
return -EMSGSIZE;
|
||||
return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT,
|
||||
ffo);
|
||||
return nla_put_sint(msg,
|
||||
DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT,
|
||||
ffo.ffo);
|
||||
}
|
||||
|
||||
static int dpll_msg_add_measured_freq(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
struct dpll_pin_ref *ref,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct dpll_device_ops *dev_ops = dpll_device_ops(ref->dpll);
|
||||
const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
|
||||
struct dpll_device *dpll = ref->dpll;
|
||||
enum dpll_feature_state state;
|
||||
u64 measured_freq;
|
||||
int ret;
|
||||
|
||||
if (!ops->measured_freq_get)
|
||||
return 0;
|
||||
ret = dev_ops->freq_monitor_get(dpll, dpll_priv(dpll),
|
||||
&state, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (state == DPLL_FEATURE_STATE_DISABLE)
|
||||
return 0;
|
||||
ret = ops->measured_freq_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
|
||||
dpll, dpll_priv(dpll), &measured_freq,
|
||||
extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (nla_put_64bit(msg, DPLL_A_PIN_MEASURED_FREQUENCY,
|
||||
sizeof(measured_freq), &measured_freq,
|
||||
DPLL_A_PIN_PAD))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -598,6 +677,9 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
if (ret)
|
||||
goto nest_cancel;
|
||||
ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack);
|
||||
if (ret)
|
||||
goto nest_cancel;
|
||||
ret = dpll_msg_add_pin_operstate(msg, pin, ref, extack);
|
||||
if (ret)
|
||||
goto nest_cancel;
|
||||
ret = dpll_msg_add_pin_prio(msg, pin, ref, extack);
|
||||
@ -607,6 +689,10 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
if (ret)
|
||||
goto nest_cancel;
|
||||
ret = dpll_msg_add_phase_offset(msg, pin, ref, extack);
|
||||
if (ret)
|
||||
goto nest_cancel;
|
||||
ret = dpll_msg_add_ffo(msg, pin, ref,
|
||||
DPLL_FFO_PIN_DEVICE, extack);
|
||||
if (ret)
|
||||
goto nest_cancel;
|
||||
nla_nest_end(msg, attr);
|
||||
@ -669,7 +755,11 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = dpll_msg_add_ffo(msg, pin, ref, extack);
|
||||
ret = dpll_msg_add_ffo(msg, pin, ref,
|
||||
DPLL_FFO_PORT_RXTX_RATE, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = dpll_msg_add_measured_freq(msg, pin, ref, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = dpll_msg_add_pin_esync(msg, pin, ref, extack);
|
||||
@ -722,6 +812,9 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = dpll_msg_add_phase_offset_avg_factor(msg, dpll, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = dpll_msg_add_freq_monitor(msg, dpll, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -948,6 +1041,32 @@ dpll_phase_offset_avg_factor_set(struct dpll_device *dpll, struct nlattr *a,
|
||||
extack);
|
||||
}
|
||||
|
||||
static int
|
||||
dpll_freq_monitor_set(struct dpll_device *dpll, struct nlattr *a,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct dpll_device_ops *ops = dpll_device_ops(dpll);
|
||||
enum dpll_feature_state state = nla_get_u32(a), old_state;
|
||||
int ret;
|
||||
|
||||
if (!(ops->freq_monitor_set && ops->freq_monitor_get)) {
|
||||
NL_SET_ERR_MSG_ATTR(extack, a,
|
||||
"dpll device not capable of frequency monitor");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
ret = ops->freq_monitor_get(dpll, dpll_priv(dpll), &old_state,
|
||||
extack);
|
||||
if (ret) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"unable to get current state of frequency monitor");
|
||||
return ret;
|
||||
}
|
||||
if (state == old_state)
|
||||
return 0;
|
||||
|
||||
return ops->freq_monitor_set(dpll, dpll_priv(dpll), state, extack);
|
||||
}
|
||||
|
||||
static int
|
||||
dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
|
||||
struct netlink_ext_ack *extack)
|
||||
@ -1878,6 +1997,12 @@ dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info)
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case DPLL_A_FREQUENCY_MONITOR:
|
||||
ret = dpll_freq_monitor_set(dpll, a,
|
||||
info->extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,12 +11,15 @@
|
||||
#include <uapi/linux/dpll.h>
|
||||
|
||||
/* Common nested types */
|
||||
const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1] = {
|
||||
const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + 1] = {
|
||||
[DPLL_A_PIN_PARENT_ID] = { .type = NLA_U32, },
|
||||
[DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
|
||||
[DPLL_A_PIN_PRIO] = { .type = NLA_U32, },
|
||||
[DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3),
|
||||
[DPLL_A_PIN_OPERSTATE] = NLA_POLICY_RANGE(NLA_U32, 1, 4),
|
||||
[DPLL_A_PIN_PHASE_OFFSET] = { .type = NLA_S64, },
|
||||
[DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET] = { .type = NLA_SINT, },
|
||||
[DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT] = { .type = NLA_SINT, },
|
||||
};
|
||||
|
||||
const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1] = {
|
||||
@ -42,11 +45,12 @@ static const struct nla_policy dpll_device_get_nl_policy[DPLL_A_ID + 1] = {
|
||||
};
|
||||
|
||||
/* DPLL_CMD_DEVICE_SET - do */
|
||||
static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_PHASE_OFFSET_AVG_FACTOR + 1] = {
|
||||
static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_FREQUENCY_MONITOR + 1] = {
|
||||
[DPLL_A_ID] = { .type = NLA_U32, },
|
||||
[DPLL_A_MODE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
|
||||
[DPLL_A_PHASE_OFFSET_MONITOR] = NLA_POLICY_MAX(NLA_U32, 1),
|
||||
[DPLL_A_PHASE_OFFSET_AVG_FACTOR] = { .type = NLA_U32, },
|
||||
[DPLL_A_FREQUENCY_MONITOR] = NLA_POLICY_MAX(NLA_U32, 1),
|
||||
};
|
||||
|
||||
/* DPLL_CMD_PIN_ID_GET - do */
|
||||
@ -114,7 +118,7 @@ static const struct genl_split_ops dpll_nl_ops[] = {
|
||||
.doit = dpll_nl_device_set_doit,
|
||||
.post_doit = dpll_post_doit,
|
||||
.policy = dpll_device_set_nl_policy,
|
||||
.maxattr = DPLL_A_PHASE_OFFSET_AVG_FACTOR,
|
||||
.maxattr = DPLL_A_FREQUENCY_MONITOR,
|
||||
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
|
||||
},
|
||||
{
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#include <uapi/linux/dpll.h>
|
||||
|
||||
/* Common nested types */
|
||||
extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1];
|
||||
extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + 1];
|
||||
extern const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1];
|
||||
extern const struct nla_policy dpll_reference_sync_nl_policy[DPLL_A_PIN_STATE + 1];
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_ZL3073X) += zl3073x.o
|
||||
zl3073x-objs := core.o devlink.o dpll.o flash.o fw.o \
|
||||
out.o prop.o ref.o synth.o
|
||||
zl3073x-objs := chan.o core.o devlink.o dpll.o \
|
||||
flash.o fw.o out.o prop.o ref.o synth.o
|
||||
|
||||
obj-$(CONFIG_ZL3073X_I2C) += zl3073x_i2c.o
|
||||
zl3073x_i2c-objs := i2c.o
|
||||
|
||||
192
drivers/dpll/zl3073x/chan.c
Normal file
192
drivers/dpll/zl3073x/chan.c
Normal file
@ -0,0 +1,192 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/dev_printk.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "chan.h"
|
||||
#include "core.h"
|
||||
|
||||
/**
|
||||
* zl3073x_chan_state_update - update DPLL channel status from HW
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
* @index: DPLL channel index
|
||||
*
|
||||
* Return: 0 on success, <0 on error
|
||||
*/
|
||||
int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index)
|
||||
{
|
||||
struct zl3073x_chan *chan = &zldev->chan[index];
|
||||
u64 val;
|
||||
int rc;
|
||||
|
||||
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MON_STATUS(index),
|
||||
&chan->mon_status);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_REFSEL_STATUS(index),
|
||||
&chan->refsel_status);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Read df_offset vs tracked reference */
|
||||
rc = zl3073x_poll_zero_u8(zldev, ZL_REG_DPLL_DF_READ(index),
|
||||
ZL_DPLL_DF_READ_SEM);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_DF_READ(index),
|
||||
ZL_DPLL_DF_READ_SEM | ZL_DPLL_DF_READ_REF_OFST);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = zl3073x_poll_zero_u8(zldev, ZL_REG_DPLL_DF_READ(index),
|
||||
ZL_DPLL_DF_READ_SEM);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = zl3073x_read_u48(zldev, ZL_REG_DPLL_DF_OFFSET(index), &val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
chan->df_offset = sign_extend64(val, 47);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_state_fetch - fetch DPLL channel state from hardware
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
* @index: DPLL channel index to fetch state for
|
||||
*
|
||||
* Reads the mode_refsel register and reference priority registers for
|
||||
* the given DPLL channel and stores the raw values for later use.
|
||||
*
|
||||
* Return: 0 on success, <0 on error
|
||||
*/
|
||||
int zl3073x_chan_state_fetch(struct zl3073x_dev *zldev, u8 index)
|
||||
{
|
||||
struct zl3073x_chan *chan = &zldev->chan[index];
|
||||
int rc, i;
|
||||
|
||||
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MODE_REFSEL(index),
|
||||
&chan->mode_refsel);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
dev_dbg(zldev->dev, "DPLL%u mode: %u, ref: %u\n", index,
|
||||
zl3073x_chan_mode_get(chan), zl3073x_chan_ref_get(chan));
|
||||
|
||||
rc = zl3073x_chan_state_update(zldev, index);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
dev_dbg(zldev->dev,
|
||||
"DPLL%u lock_state: %u, ho: %u, sel_state: %u, sel_ref: %u\n",
|
||||
index, zl3073x_chan_lock_state_get(chan),
|
||||
zl3073x_chan_is_ho_ready(chan) ? 1 : 0,
|
||||
zl3073x_chan_refsel_state_get(chan),
|
||||
zl3073x_chan_refsel_ref_get(chan));
|
||||
|
||||
guard(mutex)(&zldev->multiop_lock);
|
||||
|
||||
/* Read DPLL configuration from mailbox */
|
||||
rc = zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_RD,
|
||||
ZL_REG_DPLL_MB_MASK, BIT(index));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Read reference priority registers */
|
||||
for (i = 0; i < ARRAY_SIZE(chan->ref_prio); i++) {
|
||||
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_REF_PRIO(i),
|
||||
&chan->ref_prio[i]);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_state_get - get current DPLL channel state
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
* @index: DPLL channel index to get state for
|
||||
*
|
||||
* Return: pointer to given DPLL channel state
|
||||
*/
|
||||
const struct zl3073x_chan *zl3073x_chan_state_get(struct zl3073x_dev *zldev,
|
||||
u8 index)
|
||||
{
|
||||
return &zldev->chan[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_state_set - commit DPLL channel state changes to hardware
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
* @index: DPLL channel index to set state for
|
||||
* @chan: desired channel state
|
||||
*
|
||||
* Skips the HW write if the configuration is unchanged, and otherwise
|
||||
* writes only the changed registers to hardware. The mode_refsel register
|
||||
* is written directly, while the reference priority registers are written
|
||||
* via the DPLL mailbox interface.
|
||||
*
|
||||
* Return: 0 on success, <0 on HW error
|
||||
*/
|
||||
int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
const struct zl3073x_chan *chan)
|
||||
{
|
||||
struct zl3073x_chan *dchan = &zldev->chan[index];
|
||||
int rc, i;
|
||||
|
||||
/* Skip HW write if configuration hasn't changed */
|
||||
if (!memcmp(&dchan->cfg, &chan->cfg, sizeof(chan->cfg)))
|
||||
return 0;
|
||||
|
||||
/* Direct register write for mode_refsel */
|
||||
if (dchan->mode_refsel != chan->mode_refsel) {
|
||||
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MODE_REFSEL(index),
|
||||
chan->mode_refsel);
|
||||
if (rc)
|
||||
return rc;
|
||||
dchan->mode_refsel = chan->mode_refsel;
|
||||
}
|
||||
|
||||
/* Mailbox write for ref_prio if changed */
|
||||
if (!memcmp(dchan->ref_prio, chan->ref_prio, sizeof(chan->ref_prio))) {
|
||||
dchan->cfg = chan->cfg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
guard(mutex)(&zldev->multiop_lock);
|
||||
|
||||
/* Read DPLL configuration into mailbox */
|
||||
rc = zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_RD,
|
||||
ZL_REG_DPLL_MB_MASK, BIT(index));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Update changed ref_prio registers */
|
||||
for (i = 0; i < ARRAY_SIZE(chan->ref_prio); i++) {
|
||||
if (dchan->ref_prio[i] != chan->ref_prio[i]) {
|
||||
rc = zl3073x_write_u8(zldev,
|
||||
ZL_REG_DPLL_REF_PRIO(i),
|
||||
chan->ref_prio[i]);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Commit DPLL configuration */
|
||||
rc = zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_WR,
|
||||
ZL_REG_DPLL_MB_MASK, BIT(index));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* After successful write store new state */
|
||||
dchan->cfg = chan->cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
188
drivers/dpll/zl3073x/chan.h
Normal file
188
drivers/dpll/zl3073x/chan.h
Normal file
@ -0,0 +1,188 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _ZL3073X_CHAN_H
|
||||
#define _ZL3073X_CHAN_H
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "regs.h"
|
||||
|
||||
struct zl3073x_dev;
|
||||
|
||||
/**
|
||||
* struct zl3073x_chan - DPLL channel state
|
||||
* @mode_refsel: mode and reference selection register value
|
||||
* @ref_prio: reference priority registers (4 bits per ref, P/N packed)
|
||||
* @mon_status: monitor status register value
|
||||
* @refsel_status: reference selection status register value
|
||||
* @df_offset: frequency offset vs tracked reference in 2^-48 steps
|
||||
*/
|
||||
struct zl3073x_chan {
|
||||
struct_group(cfg,
|
||||
u8 mode_refsel;
|
||||
u8 ref_prio[ZL3073X_NUM_REFS / 2];
|
||||
);
|
||||
struct_group(stat,
|
||||
u8 mon_status;
|
||||
u8 refsel_status;
|
||||
s64 df_offset;
|
||||
);
|
||||
};
|
||||
|
||||
int zl3073x_chan_state_fetch(struct zl3073x_dev *zldev, u8 index);
|
||||
const struct zl3073x_chan *zl3073x_chan_state_get(struct zl3073x_dev *zldev,
|
||||
u8 index);
|
||||
int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
const struct zl3073x_chan *chan);
|
||||
|
||||
int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index);
|
||||
|
||||
/**
|
||||
* zl3073x_chan_df_offset_get - get cached df_offset vs tracked reference
|
||||
* @chan: pointer to channel state
|
||||
*
|
||||
* Return: frequency offset in 2^-48 steps
|
||||
*/
|
||||
static inline s64
|
||||
zl3073x_chan_df_offset_get(const struct zl3073x_chan *chan)
|
||||
{
|
||||
return chan->df_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_mode_get - get DPLL channel operating mode
|
||||
* @chan: pointer to channel state
|
||||
*
|
||||
* Return: reference selection mode of the given DPLL channel
|
||||
*/
|
||||
static inline u8 zl3073x_chan_mode_get(const struct zl3073x_chan *chan)
|
||||
{
|
||||
return FIELD_GET(ZL_DPLL_MODE_REFSEL_MODE, chan->mode_refsel);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_ref_get - get manually selected reference
|
||||
* @chan: pointer to channel state
|
||||
*
|
||||
* Return: reference selected in forced reference lock mode
|
||||
*/
|
||||
static inline u8 zl3073x_chan_ref_get(const struct zl3073x_chan *chan)
|
||||
{
|
||||
return FIELD_GET(ZL_DPLL_MODE_REFSEL_REF, chan->mode_refsel);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_mode_set - set DPLL channel operating mode
|
||||
* @chan: pointer to channel state
|
||||
* @mode: mode to set
|
||||
*/
|
||||
static inline void zl3073x_chan_mode_set(struct zl3073x_chan *chan, u8 mode)
|
||||
{
|
||||
FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_MODE, &chan->mode_refsel, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_ref_set - set manually selected reference
|
||||
* @chan: pointer to channel state
|
||||
* @ref: reference to set
|
||||
*/
|
||||
static inline void zl3073x_chan_ref_set(struct zl3073x_chan *chan, u8 ref)
|
||||
{
|
||||
FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_REF, &chan->mode_refsel, ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_ref_prio_get - get reference priority
|
||||
* @chan: pointer to channel state
|
||||
* @ref: input reference index
|
||||
*
|
||||
* Return: priority of the given reference <0, 15>
|
||||
*/
|
||||
static inline u8
|
||||
zl3073x_chan_ref_prio_get(const struct zl3073x_chan *chan, u8 ref)
|
||||
{
|
||||
u8 val = chan->ref_prio[ref / 2];
|
||||
|
||||
if (!(ref & 1))
|
||||
return FIELD_GET(ZL_DPLL_REF_PRIO_REF_P, val);
|
||||
else
|
||||
return FIELD_GET(ZL_DPLL_REF_PRIO_REF_N, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_ref_prio_set - set reference priority
|
||||
* @chan: pointer to channel state
|
||||
* @ref: input reference index
|
||||
* @prio: priority to set
|
||||
*/
|
||||
static inline void
|
||||
zl3073x_chan_ref_prio_set(struct zl3073x_chan *chan, u8 ref, u8 prio)
|
||||
{
|
||||
u8 *val = &chan->ref_prio[ref / 2];
|
||||
|
||||
if (!(ref & 1))
|
||||
FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_P, val, prio);
|
||||
else
|
||||
FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_N, val, prio);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_ref_is_selectable - check if reference is selectable
|
||||
* @chan: pointer to channel state
|
||||
* @ref: input reference index
|
||||
*
|
||||
* Return: true if the reference priority is not NONE, false otherwise
|
||||
*/
|
||||
static inline bool
|
||||
zl3073x_chan_ref_is_selectable(const struct zl3073x_chan *chan, u8 ref)
|
||||
{
|
||||
return zl3073x_chan_ref_prio_get(chan, ref) != ZL_DPLL_REF_PRIO_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_lock_state_get - get DPLL channel lock state
|
||||
* @chan: pointer to channel state
|
||||
*
|
||||
* Return: lock state of the given DPLL channel
|
||||
*/
|
||||
static inline u8 zl3073x_chan_lock_state_get(const struct zl3073x_chan *chan)
|
||||
{
|
||||
return FIELD_GET(ZL_DPLL_MON_STATUS_STATE, chan->mon_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_is_ho_ready - check if holdover is ready
|
||||
* @chan: pointer to channel state
|
||||
*
|
||||
* Return: true if holdover is ready, false otherwise
|
||||
*/
|
||||
static inline bool zl3073x_chan_is_ho_ready(const struct zl3073x_chan *chan)
|
||||
{
|
||||
return !!FIELD_GET(ZL_DPLL_MON_STATUS_HO_READY, chan->mon_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_refsel_state_get - get reference selection state
|
||||
* @chan: pointer to channel state
|
||||
*
|
||||
* Return: reference selection state of the given DPLL channel
|
||||
*/
|
||||
static inline u8 zl3073x_chan_refsel_state_get(const struct zl3073x_chan *chan)
|
||||
{
|
||||
return FIELD_GET(ZL_DPLL_REFSEL_STATUS_STATE, chan->refsel_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_chan_refsel_ref_get - get currently selected reference in auto mode
|
||||
* @chan: pointer to channel state
|
||||
*
|
||||
* Return: reference selected by the DPLL in automatic mode
|
||||
*/
|
||||
static inline u8 zl3073x_chan_refsel_ref_get(const struct zl3073x_chan *chan)
|
||||
{
|
||||
return FIELD_GET(ZL_DPLL_REFSEL_STATUS_REFSEL, chan->refsel_status);
|
||||
}
|
||||
|
||||
#endif /* _ZL3073X_CHAN_H */
|
||||
@ -20,78 +20,29 @@
|
||||
#include "dpll.h"
|
||||
#include "regs.h"
|
||||
|
||||
/* Chip IDs for zl30731 */
|
||||
static const u16 zl30731_ids[] = {
|
||||
0x0E93,
|
||||
0x1E93,
|
||||
0x2E93,
|
||||
};
|
||||
#define ZL_CHIP_INFO(_id, _nchannels, _flags) \
|
||||
{ .id = (_id), .num_channels = (_nchannels), .flags = (_flags) }
|
||||
|
||||
const struct zl3073x_chip_info zl30731_chip_info = {
|
||||
.ids = zl30731_ids,
|
||||
.num_ids = ARRAY_SIZE(zl30731_ids),
|
||||
.num_channels = 1,
|
||||
static const struct zl3073x_chip_info zl3073x_chip_ids[] = {
|
||||
ZL_CHIP_INFO(0x0E30, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
|
||||
ZL_CHIP_INFO(0x0E93, 1, ZL3073X_FLAG_REF_PHASE_COMP_32),
|
||||
ZL_CHIP_INFO(0x0E94, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
|
||||
ZL_CHIP_INFO(0x0E95, 3, ZL3073X_FLAG_REF_PHASE_COMP_32),
|
||||
ZL_CHIP_INFO(0x0E96, 4, ZL3073X_FLAG_REF_PHASE_COMP_32),
|
||||
ZL_CHIP_INFO(0x0E97, 5, ZL3073X_FLAG_REF_PHASE_COMP_32),
|
||||
ZL_CHIP_INFO(0x1E93, 1, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x1E94, 2, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x1E95, 3, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x1E96, 4, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x1E97, 5, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x1F60, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
|
||||
ZL_CHIP_INFO(0x2E93, 1, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x2E94, 2, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x2E95, 3, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x2E96, 4, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x2E97, 5, ZL3073X_FLAG_DIE_TEMP),
|
||||
ZL_CHIP_INFO(0x3FC4, 2, ZL3073X_FLAG_DIE_TEMP),
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(zl30731_chip_info, "ZL3073X");
|
||||
|
||||
/* Chip IDs for zl30732 */
|
||||
static const u16 zl30732_ids[] = {
|
||||
0x0E30,
|
||||
0x0E94,
|
||||
0x1E94,
|
||||
0x1F60,
|
||||
0x2E94,
|
||||
0x3FC4,
|
||||
};
|
||||
|
||||
const struct zl3073x_chip_info zl30732_chip_info = {
|
||||
.ids = zl30732_ids,
|
||||
.num_ids = ARRAY_SIZE(zl30732_ids),
|
||||
.num_channels = 2,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(zl30732_chip_info, "ZL3073X");
|
||||
|
||||
/* Chip IDs for zl30733 */
|
||||
static const u16 zl30733_ids[] = {
|
||||
0x0E95,
|
||||
0x1E95,
|
||||
0x2E95,
|
||||
};
|
||||
|
||||
const struct zl3073x_chip_info zl30733_chip_info = {
|
||||
.ids = zl30733_ids,
|
||||
.num_ids = ARRAY_SIZE(zl30733_ids),
|
||||
.num_channels = 3,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(zl30733_chip_info, "ZL3073X");
|
||||
|
||||
/* Chip IDs for zl30734 */
|
||||
static const u16 zl30734_ids[] = {
|
||||
0x0E96,
|
||||
0x1E96,
|
||||
0x2E96,
|
||||
};
|
||||
|
||||
const struct zl3073x_chip_info zl30734_chip_info = {
|
||||
.ids = zl30734_ids,
|
||||
.num_ids = ARRAY_SIZE(zl30734_ids),
|
||||
.num_channels = 4,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(zl30734_chip_info, "ZL3073X");
|
||||
|
||||
/* Chip IDs for zl30735 */
|
||||
static const u16 zl30735_ids[] = {
|
||||
0x0E97,
|
||||
0x1E97,
|
||||
0x2E97,
|
||||
};
|
||||
|
||||
const struct zl3073x_chip_info zl30735_chip_info = {
|
||||
.ids = zl30735_ids,
|
||||
.num_ids = ARRAY_SIZE(zl30735_ids),
|
||||
.num_channels = 5,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(zl30735_chip_info, "ZL3073X");
|
||||
|
||||
#define ZL_RANGE_OFFSET 0x80
|
||||
#define ZL_PAGE_SIZE 0x80
|
||||
@ -588,17 +539,26 @@ zl3073x_dev_state_fetch(struct zl3073x_dev *zldev)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < zldev->info->num_channels; i++) {
|
||||
rc = zl3073x_chan_state_fetch(zldev, i);
|
||||
if (rc) {
|
||||
dev_err(zldev->dev,
|
||||
"Failed to fetch channel state: %pe\n",
|
||||
ERR_PTR(rc));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
zl3073x_dev_ref_status_update(struct zl3073x_dev *zldev)
|
||||
zl3073x_dev_ref_states_update(struct zl3073x_dev *zldev)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < ZL3073X_NUM_REFS; i++) {
|
||||
rc = zl3073x_read_u8(zldev, ZL_REG_REF_MON_STATUS(i),
|
||||
&zldev->ref[i].mon_status);
|
||||
rc = zl3073x_ref_state_update(zldev, i);
|
||||
if (rc)
|
||||
dev_warn(zldev->dev,
|
||||
"Failed to get REF%u status: %pe\n", i,
|
||||
@ -606,6 +566,20 @@ zl3073x_dev_ref_status_update(struct zl3073x_dev *zldev)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zl3073x_dev_chan_states_update(struct zl3073x_dev *zldev)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < zldev->info->num_channels; i++) {
|
||||
rc = zl3073x_chan_state_update(zldev, i);
|
||||
if (rc)
|
||||
dev_warn(zldev->dev,
|
||||
"Failed to get DPLL%u state: %pe\n", i,
|
||||
ERR_PTR(rc));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_phase_offsets_update - update reference phase offsets
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
@ -658,22 +632,21 @@ int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel)
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_ffo_update - update reference fractional frequency offsets
|
||||
* zl3073x_ref_freq_meas_latch - latch reference frequency measurements
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
* @type: measurement type (ZL_REF_FREQ_MEAS_CTRL_*)
|
||||
*
|
||||
* The function asks device to update fractional frequency offsets latch
|
||||
* registers the latest measured values, reads and stores them into
|
||||
* The function waits for the previous measurement to finish, selects all
|
||||
* references and requests a new measurement of the given type.
|
||||
*
|
||||
* Return: 0 on success, <0 on error
|
||||
*/
|
||||
static int
|
||||
zl3073x_ref_ffo_update(struct zl3073x_dev *zldev)
|
||||
zl3073x_ref_freq_meas_latch(struct zl3073x_dev *zldev, u8 type)
|
||||
{
|
||||
int i, rc;
|
||||
int rc;
|
||||
|
||||
/* Per datasheet we have to wait for 'ref_freq_meas_ctrl' to be zero
|
||||
* to ensure that the measured data are coherent.
|
||||
*/
|
||||
/* Wait for previous measurement to finish */
|
||||
rc = zl3073x_poll_zero_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL,
|
||||
ZL_REF_FREQ_MEAS_CTRL);
|
||||
if (rc)
|
||||
@ -689,32 +662,43 @@ zl3073x_ref_ffo_update(struct zl3073x_dev *zldev)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Request frequency offset measurement */
|
||||
rc = zl3073x_write_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL,
|
||||
ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF);
|
||||
/* Request measurement */
|
||||
rc = zl3073x_write_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL, type);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Wait for finish */
|
||||
rc = zl3073x_poll_zero_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL,
|
||||
ZL_REF_FREQ_MEAS_CTRL);
|
||||
return zl3073x_poll_zero_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL,
|
||||
ZL_REF_FREQ_MEAS_CTRL);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_freq_meas_update - update measured input reference frequencies
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
*
|
||||
* The function asks device to latch measured input reference frequencies
|
||||
* and stores the results in the ref state.
|
||||
*
|
||||
* Return: 0 on success, <0 on error
|
||||
*/
|
||||
static int
|
||||
zl3073x_ref_freq_meas_update(struct zl3073x_dev *zldev)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
rc = zl3073x_ref_freq_meas_latch(zldev, ZL_REF_FREQ_MEAS_CTRL_REF_FREQ);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Read DPLL-to-REFx frequency offset measurements */
|
||||
/* Read measured frequencies in Hz (unsigned 32-bit, LSB = 1 Hz) */
|
||||
for (i = 0; i < ZL3073X_NUM_REFS; i++) {
|
||||
s32 value;
|
||||
u32 value;
|
||||
|
||||
/* Read value stored in units of 2^-32 signed */
|
||||
rc = zl3073x_read_u32(zldev, ZL_REG_REF_FREQ(i), &value);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Convert to ppt
|
||||
* ffo = (10^12 * value) / 2^32
|
||||
* ffo = ( 5^12 * value) / 2^20
|
||||
*/
|
||||
zldev->ref[i].ffo = mul_s64_u64_shr(value, 244140625, 20);
|
||||
zldev->ref[i].meas_freq = value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -728,8 +712,11 @@ zl3073x_dev_periodic_work(struct kthread_work *work)
|
||||
struct zl3073x_dpll *zldpll;
|
||||
int rc;
|
||||
|
||||
/* Update input references status */
|
||||
zl3073x_dev_ref_status_update(zldev);
|
||||
/* Update input references' states */
|
||||
zl3073x_dev_ref_states_update(zldev);
|
||||
|
||||
/* Update DPLL channels' states */
|
||||
zl3073x_dev_chan_states_update(zldev);
|
||||
|
||||
/* Update DPLL-to-connected-ref phase offsets registers */
|
||||
rc = zl3073x_ref_phase_offsets_update(zldev, -1);
|
||||
@ -737,12 +724,19 @@ zl3073x_dev_periodic_work(struct kthread_work *work)
|
||||
dev_warn(zldev->dev, "Failed to update phase offsets: %pe\n",
|
||||
ERR_PTR(rc));
|
||||
|
||||
/* Update references' fractional frequency offsets */
|
||||
rc = zl3073x_ref_ffo_update(zldev);
|
||||
if (rc)
|
||||
dev_warn(zldev->dev,
|
||||
"Failed to update fractional frequency offsets: %pe\n",
|
||||
ERR_PTR(rc));
|
||||
/* Update measured input reference frequencies if any DPLL has
|
||||
* frequency monitoring enabled.
|
||||
*/
|
||||
list_for_each_entry(zldpll, &zldev->dplls, list) {
|
||||
if (zldpll->freq_monitor) {
|
||||
rc = zl3073x_ref_freq_meas_update(zldev);
|
||||
if (rc)
|
||||
dev_warn(zldev->dev,
|
||||
"Failed to update measured frequencies: %pe\n",
|
||||
ERR_PTR(rc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(zldpll, &zldev->dplls, list)
|
||||
zl3073x_dpll_changes_check(zldpll);
|
||||
@ -766,8 +760,7 @@ int zl3073x_dev_phase_avg_factor_set(struct zl3073x_dev *zldev, u8 factor)
|
||||
value = (factor + 1) & 0x0f;
|
||||
|
||||
/* Update phase measurement control register */
|
||||
dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR;
|
||||
dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, value);
|
||||
FIELD_MODIFY(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, &dpll_meas_ctrl, value);
|
||||
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -942,7 +935,7 @@ static void zl3073x_dev_dpll_fini(void *ptr)
|
||||
}
|
||||
|
||||
static int
|
||||
zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
|
||||
zl3073x_devm_dpll_init(struct zl3073x_dev *zldev)
|
||||
{
|
||||
struct kthread_worker *kworker;
|
||||
struct zl3073x_dpll *zldpll;
|
||||
@ -952,7 +945,7 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
|
||||
INIT_LIST_HEAD(&zldev->dplls);
|
||||
|
||||
/* Allocate all DPLLs */
|
||||
for (i = 0; i < num_dplls; i++) {
|
||||
for (i = 0; i < zldev->info->num_channels; i++) {
|
||||
zldpll = zl3073x_dpll_alloc(zldev, i);
|
||||
if (IS_ERR(zldpll)) {
|
||||
dev_err_probe(zldev->dev, PTR_ERR(zldpll),
|
||||
@ -981,11 +974,7 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
|
||||
}
|
||||
|
||||
/* Add devres action to release DPLL related resources */
|
||||
rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
|
||||
if (rc)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
return devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
|
||||
|
||||
error:
|
||||
zl3073x_dev_dpll_fini(zldev);
|
||||
@ -996,14 +985,12 @@ error:
|
||||
/**
|
||||
* zl3073x_dev_probe - initialize zl3073x device
|
||||
* @zldev: pointer to zl3073x device
|
||||
* @chip_info: chip info based on compatible
|
||||
*
|
||||
* Common initialization of zl3073x device structure.
|
||||
*
|
||||
* Returns: 0 on success, <0 on error
|
||||
*/
|
||||
int zl3073x_dev_probe(struct zl3073x_dev *zldev,
|
||||
const struct zl3073x_chip_info *chip_info)
|
||||
int zl3073x_dev_probe(struct zl3073x_dev *zldev)
|
||||
{
|
||||
u16 id, revision, fw_ver;
|
||||
unsigned int i;
|
||||
@ -1015,17 +1002,17 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Check it matches */
|
||||
for (i = 0; i < chip_info->num_ids; i++) {
|
||||
if (id == chip_info->ids[i])
|
||||
/* Detect chip variant */
|
||||
for (i = 0; i < ARRAY_SIZE(zl3073x_chip_ids); i++) {
|
||||
if (zl3073x_chip_ids[i].id == id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == chip_info->num_ids) {
|
||||
if (i == ARRAY_SIZE(zl3073x_chip_ids))
|
||||
return dev_err_probe(zldev->dev, -ENODEV,
|
||||
"Unknown or non-match chip ID: 0x%0x\n",
|
||||
id);
|
||||
}
|
||||
"Unknown chip ID: 0x%04x\n", id);
|
||||
|
||||
zldev->info = &zl3073x_chip_ids[i];
|
||||
|
||||
/* Read revision, firmware version and custom config version */
|
||||
rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);
|
||||
@ -1064,7 +1051,7 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
|
||||
"Failed to initialize mutex\n");
|
||||
|
||||
/* Register DPLL channels */
|
||||
rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels);
|
||||
rc = zl3073x_devm_dpll_init(zldev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "chan.h"
|
||||
#include "out.h"
|
||||
#include "ref.h"
|
||||
#include "regs.h"
|
||||
@ -18,26 +19,39 @@ struct device;
|
||||
struct regmap;
|
||||
struct zl3073x_dpll;
|
||||
|
||||
/*
|
||||
* Hardware limits for ZL3073x chip family
|
||||
|
||||
enum zl3073x_flags {
|
||||
ZL3073X_FLAG_REF_PHASE_COMP_32_BIT,
|
||||
ZL3073X_FLAG_DIE_TEMP_BIT,
|
||||
ZL3073X_FLAGS_NBITS /* must be last */
|
||||
};
|
||||
|
||||
#define __ZL3073X_FLAG(name) BIT(ZL3073X_FLAG_ ## name ## _BIT)
|
||||
#define ZL3073X_FLAG_REF_PHASE_COMP_32 __ZL3073X_FLAG(REF_PHASE_COMP_32)
|
||||
#define ZL3073X_FLAG_DIE_TEMP __ZL3073X_FLAG(DIE_TEMP)
|
||||
|
||||
/**
|
||||
* struct zl3073x_chip_info - chip variant identification
|
||||
* @id: chip ID
|
||||
* @num_channels: number of DPLL channels supported by this variant
|
||||
* @flags: chip variant flags
|
||||
*/
|
||||
#define ZL3073X_MAX_CHANNELS 5
|
||||
#define ZL3073X_NUM_REFS 10
|
||||
#define ZL3073X_NUM_OUTS 10
|
||||
#define ZL3073X_NUM_SYNTHS 5
|
||||
#define ZL3073X_NUM_INPUT_PINS ZL3073X_NUM_REFS
|
||||
#define ZL3073X_NUM_OUTPUT_PINS (ZL3073X_NUM_OUTS * 2)
|
||||
#define ZL3073X_NUM_PINS (ZL3073X_NUM_INPUT_PINS + \
|
||||
ZL3073X_NUM_OUTPUT_PINS)
|
||||
struct zl3073x_chip_info {
|
||||
u16 id;
|
||||
u8 num_channels;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zl3073x_dev - zl3073x device
|
||||
* @dev: pointer to device
|
||||
* @regmap: regmap to access device registers
|
||||
* @info: detected chip info
|
||||
* @multiop_lock: to serialize multiple register operations
|
||||
* @ref: array of input references' invariants
|
||||
* @out: array of outs' invariants
|
||||
* @synth: array of synths' invariants
|
||||
* @chan: array of DPLL channels' state
|
||||
* @dplls: list of DPLLs
|
||||
* @kworker: thread for periodic work
|
||||
* @work: periodic work
|
||||
@ -45,14 +59,16 @@ struct zl3073x_dpll;
|
||||
* @phase_avg_factor: phase offset measurement averaging factor
|
||||
*/
|
||||
struct zl3073x_dev {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct mutex multiop_lock;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
const struct zl3073x_chip_info *info;
|
||||
struct mutex multiop_lock;
|
||||
|
||||
/* Invariants */
|
||||
struct zl3073x_ref ref[ZL3073X_NUM_REFS];
|
||||
struct zl3073x_out out[ZL3073X_NUM_OUTS];
|
||||
struct zl3073x_synth synth[ZL3073X_NUM_SYNTHS];
|
||||
struct zl3073x_chan chan[ZL3073X_MAX_CHANNELS];
|
||||
|
||||
/* DPLL channels */
|
||||
struct list_head dplls;
|
||||
@ -66,22 +82,10 @@ struct zl3073x_dev {
|
||||
u8 phase_avg_factor;
|
||||
};
|
||||
|
||||
struct zl3073x_chip_info {
|
||||
const u16 *ids;
|
||||
size_t num_ids;
|
||||
int num_channels;
|
||||
};
|
||||
|
||||
extern const struct zl3073x_chip_info zl30731_chip_info;
|
||||
extern const struct zl3073x_chip_info zl30732_chip_info;
|
||||
extern const struct zl3073x_chip_info zl30733_chip_info;
|
||||
extern const struct zl3073x_chip_info zl30734_chip_info;
|
||||
extern const struct zl3073x_chip_info zl30735_chip_info;
|
||||
extern const struct regmap_config zl3073x_regmap_config;
|
||||
|
||||
struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
|
||||
int zl3073x_dev_probe(struct zl3073x_dev *zldev,
|
||||
const struct zl3073x_chip_info *chip_info);
|
||||
int zl3073x_dev_probe(struct zl3073x_dev *zldev);
|
||||
|
||||
int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full);
|
||||
void zl3073x_dev_stop(struct zl3073x_dev *zldev);
|
||||
@ -144,6 +148,21 @@ int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
|
||||
|
||||
int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel);
|
||||
|
||||
/**
|
||||
* zl3073x_dev_is_ref_phase_comp_32bit - check ref phase comp register size
|
||||
* @zldev: pointer to zl3073x device
|
||||
*
|
||||
* Some chip IDs have a 32-bit wide ref_phase_offset_comp register instead
|
||||
* of the default 48-bit.
|
||||
*
|
||||
* Return: true if the register is 32-bit, false if 48-bit
|
||||
*/
|
||||
static inline bool
|
||||
zl3073x_dev_is_ref_phase_comp_32bit(struct zl3073x_dev *zldev)
|
||||
{
|
||||
return zldev->info->flags & ZL3073X_FLAG_REF_PHASE_COMP_32;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
zl3073x_is_n_pin(u8 id)
|
||||
{
|
||||
@ -301,6 +320,36 @@ u8 zl3073x_dev_out_dpll_get(struct zl3073x_dev *zldev, u8 index)
|
||||
return zl3073x_synth_dpll_get(synth);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_dev_output_pin_freq_get - get output pin frequency
|
||||
* @zldev: pointer to zl3073x device
|
||||
* @id: output pin id
|
||||
*
|
||||
* Computes the output pin frequency based on the synth frequency, output
|
||||
* divisor, and signal format. For N-div formats, N-pin frequency is
|
||||
* additionally divided by esync_n_period.
|
||||
*
|
||||
* Return: frequency of the given output pin in Hz
|
||||
*/
|
||||
static inline u32
|
||||
zl3073x_dev_output_pin_freq_get(struct zl3073x_dev *zldev, u8 id)
|
||||
{
|
||||
const struct zl3073x_synth *synth;
|
||||
const struct zl3073x_out *out;
|
||||
u8 out_id;
|
||||
u32 freq;
|
||||
|
||||
out_id = zl3073x_output_pin_out_get(id);
|
||||
out = zl3073x_out_state_get(zldev, out_id);
|
||||
synth = zl3073x_synth_state_get(zldev, zl3073x_out_synth_get(out));
|
||||
freq = zl3073x_synth_freq_get(synth) / out->div;
|
||||
|
||||
if (zl3073x_out_is_ndiv(out) && zl3073x_is_n_pin(id))
|
||||
freq /= out->esync_n_period;
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_dev_out_is_diff - check if the given output is differential
|
||||
* @zldev: pointer to zl3073x device
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -13,10 +13,10 @@
|
||||
* @list: this DPLL list entry
|
||||
* @dev: pointer to multi-function parent device
|
||||
* @id: DPLL index
|
||||
* @refsel_mode: reference selection mode
|
||||
* @forced_ref: selected reference in forced reference lock mode
|
||||
* @check_count: periodic check counter
|
||||
* @phase_monitor: is phase offset monitor enabled
|
||||
* @freq_monitor: is frequency monitor enabled
|
||||
* @ops: DPLL device operations for this instance
|
||||
* @dpll_dev: pointer to registered DPLL device
|
||||
* @tracker: tracking object for the acquired reference
|
||||
* @lock_status: last saved DPLL lock status
|
||||
@ -27,10 +27,10 @@ struct zl3073x_dpll {
|
||||
struct list_head list;
|
||||
struct zl3073x_dev *dev;
|
||||
u8 id;
|
||||
u8 refsel_mode;
|
||||
u8 forced_ref;
|
||||
u8 check_count;
|
||||
bool phase_monitor;
|
||||
bool freq_monitor;
|
||||
struct dpll_device_ops ops;
|
||||
struct dpll_device *dpll_dev;
|
||||
dpll_tracker tracker;
|
||||
enum dpll_lock_status lock_status;
|
||||
|
||||
@ -194,8 +194,7 @@ zl3073x_flash_cmd_wait(struct zl3073x_dev *zldev, u32 operation,
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
value &= ~ZL_WRITE_FLASH_OP;
|
||||
value |= FIELD_PREP(ZL_WRITE_FLASH_OP, operation);
|
||||
FIELD_MODIFY(ZL_WRITE_FLASH_OP, &value, operation);
|
||||
|
||||
rc = zl3073x_write_u8(zldev, ZL_REG_WRITE_FLASH, value);
|
||||
if (rc)
|
||||
|
||||
@ -22,40 +22,25 @@ static int zl3073x_i2c_probe(struct i2c_client *client)
|
||||
return dev_err_probe(dev, PTR_ERR(zldev->regmap),
|
||||
"Failed to initialize regmap\n");
|
||||
|
||||
return zl3073x_dev_probe(zldev, i2c_get_match_data(client));
|
||||
return zl3073x_dev_probe(zldev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id zl3073x_i2c_id[] = {
|
||||
{
|
||||
.name = "zl30731",
|
||||
.driver_data = (kernel_ulong_t)&zl30731_chip_info,
|
||||
},
|
||||
{
|
||||
.name = "zl30732",
|
||||
.driver_data = (kernel_ulong_t)&zl30732_chip_info,
|
||||
},
|
||||
{
|
||||
.name = "zl30733",
|
||||
.driver_data = (kernel_ulong_t)&zl30733_chip_info,
|
||||
},
|
||||
{
|
||||
.name = "zl30734",
|
||||
.driver_data = (kernel_ulong_t)&zl30734_chip_info,
|
||||
},
|
||||
{
|
||||
.name = "zl30735",
|
||||
.driver_data = (kernel_ulong_t)&zl30735_chip_info,
|
||||
},
|
||||
{ "zl30731" },
|
||||
{ "zl30732" },
|
||||
{ "zl30733" },
|
||||
{ "zl30734" },
|
||||
{ "zl30735" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, zl3073x_i2c_id);
|
||||
|
||||
static const struct of_device_id zl3073x_i2c_of_match[] = {
|
||||
{ .compatible = "microchip,zl30731", .data = &zl30731_chip_info },
|
||||
{ .compatible = "microchip,zl30732", .data = &zl30732_chip_info },
|
||||
{ .compatible = "microchip,zl30733", .data = &zl30733_chip_info },
|
||||
{ .compatible = "microchip,zl30734", .data = &zl30734_chip_info },
|
||||
{ .compatible = "microchip,zl30735", .data = &zl30735_chip_info },
|
||||
{ .compatible = "microchip,zl30731" },
|
||||
{ .compatible = "microchip,zl30732" },
|
||||
{ .compatible = "microchip,zl30733" },
|
||||
{ .compatible = "microchip,zl30734" },
|
||||
{ .compatible = "microchip,zl30735" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zl3073x_i2c_of_match);
|
||||
|
||||
@ -106,12 +106,32 @@ const struct zl3073x_out *zl3073x_out_state_get(struct zl3073x_dev *zldev,
|
||||
return &zldev->out[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_out_state_set - commit output state changes to hardware
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
* @index: output index to set state for
|
||||
* @out: desired output state
|
||||
*
|
||||
* Validates that invariant fields have not been modified, skips the HW
|
||||
* write if the mutable configuration is unchanged, and otherwise writes
|
||||
* only the changed cfg fields to hardware via the mailbox interface.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if invariants changed, <0 on HW error
|
||||
*/
|
||||
int zl3073x_out_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
const struct zl3073x_out *out)
|
||||
{
|
||||
struct zl3073x_out *dout = &zldev->out[index];
|
||||
int rc;
|
||||
|
||||
/* Reject attempts to change invariant fields (set at fetch only) */
|
||||
if (WARN_ON(memcmp(&dout->inv, &out->inv, sizeof(out->inv))))
|
||||
return -EINVAL;
|
||||
|
||||
/* Skip HW write if configuration hasn't changed */
|
||||
if (!memcmp(&dout->cfg, &out->cfg, sizeof(out->cfg)))
|
||||
return 0;
|
||||
|
||||
guard(mutex)(&zldev->multiop_lock);
|
||||
|
||||
/* Read output configuration into mailbox */
|
||||
@ -146,12 +166,7 @@ int zl3073x_out_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
return rc;
|
||||
|
||||
/* After successful commit store new state */
|
||||
dout->div = out->div;
|
||||
dout->width = out->width;
|
||||
dout->esync_n_period = out->esync_n_period;
|
||||
dout->esync_n_width = out->esync_n_width;
|
||||
dout->mode = out->mode;
|
||||
dout->phase_comp = out->phase_comp;
|
||||
dout->cfg = out->cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#define _ZL3073X_OUT_H
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "regs.h"
|
||||
@ -17,17 +18,21 @@ struct zl3073x_dev;
|
||||
* @esync_n_period: embedded sync or n-pin period (for n-div formats)
|
||||
* @esync_n_width: embedded sync or n-pin pulse width
|
||||
* @phase_comp: phase compensation
|
||||
* @ctrl: output control
|
||||
* @mode: output mode
|
||||
* @ctrl: output control
|
||||
*/
|
||||
struct zl3073x_out {
|
||||
u32 div;
|
||||
u32 width;
|
||||
u32 esync_n_period;
|
||||
u32 esync_n_width;
|
||||
s32 phase_comp;
|
||||
u8 ctrl;
|
||||
u8 mode;
|
||||
struct_group(cfg, /* Config */
|
||||
u32 div;
|
||||
u32 width;
|
||||
u32 esync_n_period;
|
||||
u32 esync_n_width;
|
||||
s32 phase_comp;
|
||||
u8 mode;
|
||||
);
|
||||
struct_group(inv, /* Invariants */
|
||||
u8 ctrl;
|
||||
);
|
||||
};
|
||||
|
||||
int zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index);
|
||||
@ -37,6 +42,28 @@ const struct zl3073x_out *zl3073x_out_state_get(struct zl3073x_dev *zldev,
|
||||
int zl3073x_out_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
const struct zl3073x_out *out);
|
||||
|
||||
/**
|
||||
* zl3073x_out_clock_type_get - get output clock type
|
||||
* @out: pointer to out state
|
||||
*
|
||||
* Return: clock type of given output (ZL_OUTPUT_MODE_CLOCK_TYPE_*)
|
||||
*/
|
||||
static inline u8 zl3073x_out_clock_type_get(const struct zl3073x_out *out)
|
||||
{
|
||||
return FIELD_GET(ZL_OUTPUT_MODE_CLOCK_TYPE, out->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_out_clock_type_set - set output clock type
|
||||
* @out: pointer to out state
|
||||
* @type: clock type (ZL_OUTPUT_MODE_CLOCK_TYPE_*)
|
||||
*/
|
||||
static inline void
|
||||
zl3073x_out_clock_type_set(struct zl3073x_out *out, u8 type)
|
||||
{
|
||||
FIELD_MODIFY(ZL_OUTPUT_MODE_CLOCK_TYPE, &out->mode, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_out_signal_format_get - get output signal format
|
||||
* @out: pointer to out state
|
||||
@ -79,6 +106,23 @@ static inline bool zl3073x_out_is_enabled(const struct zl3073x_out *out)
|
||||
return !!FIELD_GET(ZL_OUTPUT_CTRL_EN, out->ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_out_is_ndiv - check if the given output is in N-div mode
|
||||
* @out: pointer to out state
|
||||
*
|
||||
* Return: true if output is in N-div mode, false otherwise
|
||||
*/
|
||||
static inline bool zl3073x_out_is_ndiv(const struct zl3073x_out *out)
|
||||
{
|
||||
switch (zl3073x_out_signal_format_get(out)) {
|
||||
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV:
|
||||
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_out_synth_get - get synth connected to given output
|
||||
* @out: pointer to out state
|
||||
|
||||
@ -193,9 +193,10 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
|
||||
{
|
||||
struct dpll_pin_frequency *ranges;
|
||||
struct zl3073x_pin_props *props;
|
||||
int i, j, num_freqs, rc;
|
||||
int i, j, num_freqs = 0, rc;
|
||||
u64 *freqs = NULL;
|
||||
const char *type;
|
||||
u64 *freqs;
|
||||
u32 curr_freq;
|
||||
|
||||
props = kzalloc(sizeof(*props), GFP_KERNEL);
|
||||
if (!props)
|
||||
@ -207,6 +208,7 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
|
||||
props->dpll_props.capabilities =
|
||||
DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
|
||||
DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
|
||||
curr_freq = zl3073x_dev_ref_freq_get(zldev, index);
|
||||
} else {
|
||||
u8 out, synth;
|
||||
u32 f;
|
||||
@ -220,6 +222,7 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
|
||||
synth = zl3073x_dev_out_synth_get(zldev, out);
|
||||
f = 2 * zl3073x_dev_synth_freq_get(zldev, synth);
|
||||
props->dpll_props.phase_gran = f ? div_u64(PSEC_PER_SEC, f) : 1;
|
||||
curr_freq = zl3073x_dev_output_pin_freq_get(zldev, index);
|
||||
}
|
||||
|
||||
props->dpll_props.phase_range.min = S32_MIN;
|
||||
@ -230,7 +233,7 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
|
||||
/* Get firmware node for the given pin */
|
||||
rc = zl3073x_prop_pin_fwnode_get(zldev, props, dir, index);
|
||||
if (rc)
|
||||
return props; /* Return if it does not exist */
|
||||
goto skip_fwnode_props;
|
||||
|
||||
/* Look for label property and store the value as board label */
|
||||
fwnode_property_read_string(props->fwnode, "label",
|
||||
@ -264,9 +267,10 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
|
||||
/* Read supported frequencies property if it is specified */
|
||||
num_freqs = fwnode_property_count_u64(props->fwnode,
|
||||
"supported-frequencies-hz");
|
||||
if (num_freqs <= 0)
|
||||
/* Return if the property does not exist or number is 0 */
|
||||
return props;
|
||||
if (num_freqs <= 0) {
|
||||
num_freqs = 0;
|
||||
goto skip_fwnode_props;
|
||||
}
|
||||
|
||||
/* The firmware node specifies list of supported frequencies while
|
||||
* DPLL core pin properties requires list of frequency ranges.
|
||||
@ -283,19 +287,25 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
|
||||
"supported-frequencies-hz", freqs,
|
||||
num_freqs);
|
||||
|
||||
/* Allocate frequency ranges list and fill it */
|
||||
ranges = kcalloc(num_freqs, sizeof(*ranges), GFP_KERNEL);
|
||||
skip_fwnode_props:
|
||||
/* Allocate frequency ranges list - extra slot for current frequency */
|
||||
ranges = kcalloc(num_freqs + 1, sizeof(*ranges), GFP_KERNEL);
|
||||
if (!ranges) {
|
||||
rc = -ENOMEM;
|
||||
goto err_alloc_ranges;
|
||||
}
|
||||
|
||||
/* Convert list of frequencies to list of frequency ranges but
|
||||
* filter-out frequencies that are not representable by device
|
||||
/* Start with current frequency at index 0 */
|
||||
ranges[0] = (struct dpll_pin_frequency)DPLL_PIN_FREQUENCY(curr_freq);
|
||||
|
||||
/* Add frequencies from firmware node, skipping current frequency
|
||||
* and filtering out frequencies not representable by device
|
||||
*/
|
||||
for (i = 0, j = 0; i < num_freqs; i++) {
|
||||
for (i = 0, j = 1; i < num_freqs; i++) {
|
||||
struct dpll_pin_frequency freq = DPLL_PIN_FREQUENCY(freqs[i]);
|
||||
|
||||
if (freqs[i] == curr_freq)
|
||||
continue;
|
||||
if (zl3073x_pin_check_freq(zldev, dir, index, freqs[i])) {
|
||||
ranges[j] = freq;
|
||||
j++;
|
||||
|
||||
@ -51,6 +51,21 @@ zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_state_update - update input reference status from HW
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
* @index: input reference index
|
||||
*
|
||||
* Return: 0 on success, <0 on error
|
||||
*/
|
||||
int zl3073x_ref_state_update(struct zl3073x_dev *zldev, u8 index)
|
||||
{
|
||||
struct zl3073x_ref *ref = &zldev->ref[index];
|
||||
|
||||
return zl3073x_read_u8(zldev, ZL_REG_REF_MON_STATUS(index),
|
||||
&ref->mon_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_state_fetch - fetch input reference state from hardware
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
@ -73,18 +88,17 @@ int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
|
||||
struct zl3073x_ref *p_ref = ref - 1; /* P-pin counterpart*/
|
||||
|
||||
/* Copy the shared items from the P-pin */
|
||||
ref->config = p_ref->config;
|
||||
ref->esync_n_div = p_ref->esync_n_div;
|
||||
ref->freq_base = p_ref->freq_base;
|
||||
ref->freq_mult = p_ref->freq_mult;
|
||||
ref->freq_ratio_m = p_ref->freq_ratio_m;
|
||||
ref->freq_ratio_n = p_ref->freq_ratio_n;
|
||||
ref->phase_comp = p_ref->phase_comp;
|
||||
ref->sync_ctrl = p_ref->sync_ctrl;
|
||||
ref->cfg = p_ref->cfg;
|
||||
ref->inv = p_ref->inv;
|
||||
|
||||
return 0; /* Finish - no non-shared items for now */
|
||||
}
|
||||
|
||||
/* Read reference status */
|
||||
rc = zl3073x_ref_state_update(zldev, index);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
guard(mutex)(&zldev->multiop_lock);
|
||||
|
||||
/* Read reference configuration */
|
||||
@ -121,8 +135,16 @@ int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
|
||||
return rc;
|
||||
|
||||
/* Read phase compensation register */
|
||||
rc = zl3073x_read_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
|
||||
&ref->phase_comp);
|
||||
if (zl3073x_dev_is_ref_phase_comp_32bit(zldev)) {
|
||||
u32 val;
|
||||
|
||||
rc = zl3073x_read_u32(zldev, ZL_REG_REF_PHASE_OFFSET_COMP_32,
|
||||
&val);
|
||||
ref->phase_comp = val;
|
||||
} else {
|
||||
rc = zl3073x_read_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
|
||||
&ref->phase_comp);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -146,12 +168,32 @@ zl3073x_ref_state_get(struct zl3073x_dev *zldev, u8 index)
|
||||
return &zldev->ref[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_state_set - commit input reference state changes to hardware
|
||||
* @zldev: pointer to zl3073x_dev structure
|
||||
* @index: input reference index to set state for
|
||||
* @ref: desired reference state
|
||||
*
|
||||
* Validates that invariant fields have not been modified, skips the HW
|
||||
* write if the mutable configuration is unchanged, and otherwise writes
|
||||
* only the changed cfg fields to hardware via the mailbox interface.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if invariants changed, <0 on HW error
|
||||
*/
|
||||
int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
const struct zl3073x_ref *ref)
|
||||
{
|
||||
struct zl3073x_ref *dref = &zldev->ref[index];
|
||||
int rc;
|
||||
|
||||
/* Reject attempts to change invariant fields (set at init only) */
|
||||
if (WARN_ON(memcmp(&dref->inv, &ref->inv, sizeof(ref->inv))))
|
||||
return -EINVAL;
|
||||
|
||||
/* Skip HW write if configuration hasn't changed */
|
||||
if (!memcmp(&dref->cfg, &ref->cfg, sizeof(ref->cfg)))
|
||||
return 0;
|
||||
|
||||
guard(mutex)(&zldev->multiop_lock);
|
||||
|
||||
/* Read reference configuration into mailbox */
|
||||
@ -179,9 +221,16 @@ int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
if (!rc && dref->sync_ctrl != ref->sync_ctrl)
|
||||
rc = zl3073x_write_u8(zldev, ZL_REG_REF_SYNC_CTRL,
|
||||
ref->sync_ctrl);
|
||||
if (!rc && dref->phase_comp != ref->phase_comp)
|
||||
rc = zl3073x_write_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
|
||||
ref->phase_comp);
|
||||
if (!rc && dref->phase_comp != ref->phase_comp) {
|
||||
if (zl3073x_dev_is_ref_phase_comp_32bit(zldev))
|
||||
rc = zl3073x_write_u32(zldev,
|
||||
ZL_REG_REF_PHASE_OFFSET_COMP_32,
|
||||
ref->phase_comp);
|
||||
else
|
||||
rc = zl3073x_write_u48(zldev,
|
||||
ZL_REG_REF_PHASE_OFFSET_COMP,
|
||||
ref->phase_comp);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -192,13 +241,7 @@ int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
return rc;
|
||||
|
||||
/* After successful commit store new state */
|
||||
dref->freq_base = ref->freq_base;
|
||||
dref->freq_mult = ref->freq_mult;
|
||||
dref->freq_ratio_m = ref->freq_ratio_m;
|
||||
dref->freq_ratio_n = ref->freq_ratio_n;
|
||||
dref->esync_n_div = ref->esync_n_div;
|
||||
dref->sync_ctrl = ref->sync_ctrl;
|
||||
dref->phase_comp = ref->phase_comp;
|
||||
dref->cfg = ref->cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "regs.h"
|
||||
@ -13,28 +14,34 @@ struct zl3073x_dev;
|
||||
|
||||
/**
|
||||
* struct zl3073x_ref - input reference state
|
||||
* @ffo: current fractional frequency offset
|
||||
* @phase_comp: phase compensation
|
||||
* @esync_n_div: divisor for embedded sync or n-divided signal formats
|
||||
* @freq_base: frequency base
|
||||
* @freq_mult: frequnecy multiplier
|
||||
* @freq_ratio_m: FEC mode multiplier
|
||||
* @freq_ratio_n: FEC mode divisor
|
||||
* @config: reference config
|
||||
* @sync_ctrl: reference sync control
|
||||
* @config: reference config
|
||||
* @meas_freq: measured input frequency in Hz
|
||||
* @mon_status: reference monitor status
|
||||
*/
|
||||
struct zl3073x_ref {
|
||||
s64 ffo;
|
||||
u64 phase_comp;
|
||||
u32 esync_n_div;
|
||||
u16 freq_base;
|
||||
u16 freq_mult;
|
||||
u16 freq_ratio_m;
|
||||
u16 freq_ratio_n;
|
||||
u8 config;
|
||||
u8 sync_ctrl;
|
||||
u8 mon_status;
|
||||
struct_group(cfg, /* Configuration */
|
||||
u64 phase_comp;
|
||||
u32 esync_n_div;
|
||||
u16 freq_base;
|
||||
u16 freq_mult;
|
||||
u16 freq_ratio_m;
|
||||
u16 freq_ratio_n;
|
||||
u8 sync_ctrl;
|
||||
);
|
||||
struct_group(inv, /* Invariants */
|
||||
u8 config;
|
||||
);
|
||||
struct_group(stat, /* Status */
|
||||
u32 meas_freq;
|
||||
u8 mon_status;
|
||||
);
|
||||
};
|
||||
|
||||
int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index);
|
||||
@ -45,18 +52,20 @@ const struct zl3073x_ref *zl3073x_ref_state_get(struct zl3073x_dev *zldev,
|
||||
int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
|
||||
const struct zl3073x_ref *ref);
|
||||
|
||||
int zl3073x_ref_state_update(struct zl3073x_dev *zldev, u8 index);
|
||||
|
||||
int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult);
|
||||
|
||||
/**
|
||||
* zl3073x_ref_ffo_get - get current fractional frequency offset
|
||||
* zl3073x_ref_meas_freq_get - get measured input frequency
|
||||
* @ref: pointer to ref state
|
||||
*
|
||||
* Return: the latest measured fractional frequency offset
|
||||
* Return: measured input frequency in Hz
|
||||
*/
|
||||
static inline s64
|
||||
zl3073x_ref_ffo_get(const struct zl3073x_ref *ref)
|
||||
static inline u32
|
||||
zl3073x_ref_meas_freq_get(const struct zl3073x_ref *ref)
|
||||
{
|
||||
return ref->ffo;
|
||||
return ref->meas_freq;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,10 +100,58 @@ zl3073x_ref_freq_set(struct zl3073x_ref *ref, u32 freq)
|
||||
|
||||
ref->freq_base = base;
|
||||
ref->freq_mult = mult;
|
||||
ref->freq_ratio_m = 1;
|
||||
ref->freq_ratio_n = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_sync_mode_get - get sync control mode
|
||||
* @ref: pointer to ref state
|
||||
*
|
||||
* Return: sync control mode (ZL_REF_SYNC_CTRL_MODE_*)
|
||||
*/
|
||||
static inline u8
|
||||
zl3073x_ref_sync_mode_get(const struct zl3073x_ref *ref)
|
||||
{
|
||||
return FIELD_GET(ZL_REF_SYNC_CTRL_MODE, ref->sync_ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_sync_mode_set - set sync control mode
|
||||
* @ref: pointer to ref state
|
||||
* @mode: sync control mode (ZL_REF_SYNC_CTRL_MODE_*)
|
||||
*/
|
||||
static inline void
|
||||
zl3073x_ref_sync_mode_set(struct zl3073x_ref *ref, u8 mode)
|
||||
{
|
||||
FIELD_MODIFY(ZL_REF_SYNC_CTRL_MODE, &ref->sync_ctrl, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_sync_pair_get - get sync pair reference index
|
||||
* @ref: pointer to ref state
|
||||
*
|
||||
* Return: paired reference index
|
||||
*/
|
||||
static inline u8
|
||||
zl3073x_ref_sync_pair_get(const struct zl3073x_ref *ref)
|
||||
{
|
||||
return FIELD_GET(ZL_REF_SYNC_CTRL_PAIR, ref->sync_ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_sync_pair_set - set sync pair reference index
|
||||
* @ref: pointer to ref state
|
||||
* @pair: paired reference index
|
||||
*/
|
||||
static inline void
|
||||
zl3073x_ref_sync_pair_set(struct zl3073x_ref *ref, u8 pair)
|
||||
{
|
||||
FIELD_MODIFY(ZL_REF_SYNC_CTRL_PAIR, &ref->sync_ctrl, pair);
|
||||
}
|
||||
|
||||
/**
|
||||
* zl3073x_ref_is_diff - check if the given input reference is differential
|
||||
* @ref: pointer to ref state
|
||||
|
||||
@ -6,6 +6,18 @@
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
/*
|
||||
* Hardware limits for ZL3073x chip family
|
||||
*/
|
||||
#define ZL3073X_MAX_CHANNELS 5
|
||||
#define ZL3073X_NUM_REFS 10
|
||||
#define ZL3073X_NUM_OUTS 10
|
||||
#define ZL3073X_NUM_SYNTHS 5
|
||||
#define ZL3073X_NUM_INPUT_PINS ZL3073X_NUM_REFS
|
||||
#define ZL3073X_NUM_OUTPUT_PINS (ZL3073X_NUM_OUTS * 2)
|
||||
#define ZL3073X_NUM_PINS (ZL3073X_NUM_INPUT_PINS + \
|
||||
ZL3073X_NUM_OUTPUT_PINS)
|
||||
|
||||
/*
|
||||
* Register address structure:
|
||||
* ===========================
|
||||
@ -78,13 +90,22 @@
|
||||
#define ZL_REG_RESET_STATUS ZL_REG(0, 0x18, 1)
|
||||
#define ZL_REG_RESET_STATUS_RESET BIT(0)
|
||||
|
||||
#define ZL_REG_DIE_TEMP_STATUS ZL_REG(0, 0x44, 2)
|
||||
|
||||
/*************************
|
||||
* Register Page 2, Status
|
||||
*************************/
|
||||
|
||||
#define ZL_REG_REF_MON_STATUS(_idx) \
|
||||
ZL_REG_IDX(_idx, 2, 0x02, 1, ZL3073X_NUM_REFS, 1)
|
||||
#define ZL_REF_MON_STATUS_OK 0 /* all bits zeroed */
|
||||
#define ZL_REF_MON_STATUS_OK 0
|
||||
#define ZL_REF_MON_STATUS_LOS BIT(0)
|
||||
#define ZL_REF_MON_STATUS_SCM BIT(1)
|
||||
#define ZL_REF_MON_STATUS_CFM BIT(2)
|
||||
#define ZL_REF_MON_STATUS_GST BIT(3)
|
||||
#define ZL_REF_MON_STATUS_PFM BIT(4)
|
||||
#define ZL_REF_MON_STATUS_ESYNC BIT(6)
|
||||
#define ZL_REF_MON_STATUS_SPLIT_XO BIT(7)
|
||||
|
||||
#define ZL_REG_DPLL_MON_STATUS(_idx) \
|
||||
ZL_REG_IDX(_idx, 2, 0x10, 1, ZL3073X_MAX_CHANNELS, 1)
|
||||
@ -143,6 +164,11 @@
|
||||
#define ZL_DPLL_MODE_REFSEL_MODE_NCO 4
|
||||
#define ZL_DPLL_MODE_REFSEL_REF GENMASK(7, 4)
|
||||
|
||||
#define ZL_REG_DPLL_DF_READ(_idx) \
|
||||
ZL_REG_IDX(_idx, 5, 0x28, 1, ZL3073X_MAX_CHANNELS, 1)
|
||||
#define ZL_DPLL_DF_READ_SEM BIT(4)
|
||||
#define ZL_DPLL_DF_READ_REF_OFST BIT(3)
|
||||
|
||||
#define ZL_REG_DPLL_MEAS_CTRL ZL_REG(5, 0x50, 1)
|
||||
#define ZL_DPLL_MEAS_CTRL_EN BIT(0)
|
||||
#define ZL_DPLL_MEAS_CTRL_AVG_FACTOR GENMASK(7, 4)
|
||||
@ -155,6 +181,16 @@
|
||||
#define ZL_REG_DPLL_PHASE_ERR_DATA(_idx) \
|
||||
ZL_REG_IDX(_idx, 5, 0x55, 6, ZL3073X_MAX_CHANNELS, 6)
|
||||
|
||||
/*******************************
|
||||
* Register Pages 6-7, DPLL Data
|
||||
*******************************/
|
||||
|
||||
#define ZL_REG_DPLL_DF_OFFSET_03(_idx) \
|
||||
ZL_REG_IDX(_idx, 6, 0x00, 6, 4, 0x20)
|
||||
#define ZL_REG_DPLL_DF_OFFSET_4 ZL_REG(7, 0x00, 6)
|
||||
#define ZL_REG_DPLL_DF_OFFSET(_idx) \
|
||||
((_idx) < 4 ? ZL_REG_DPLL_DF_OFFSET_03(_idx) : ZL_REG_DPLL_DF_OFFSET_4)
|
||||
|
||||
/***********************************
|
||||
* Register Page 9, Synth and Output
|
||||
***********************************/
|
||||
@ -194,11 +230,14 @@
|
||||
#define ZL_REF_CONFIG_DIFF_EN BIT(2)
|
||||
|
||||
#define ZL_REG_REF_PHASE_OFFSET_COMP ZL_REG(10, 0x28, 6)
|
||||
#define ZL_REG_REF_PHASE_OFFSET_COMP_32 ZL_REG(10, 0x28, 4)
|
||||
|
||||
#define ZL_REG_REF_SYNC_CTRL ZL_REG(10, 0x2e, 1)
|
||||
#define ZL_REF_SYNC_CTRL_MODE GENMASK(2, 0)
|
||||
#define ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR_OFF 0
|
||||
#define ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR 1
|
||||
#define ZL_REF_SYNC_CTRL_MODE_50_50_ESYNC_25_75 2
|
||||
#define ZL_REF_SYNC_CTRL_PAIR GENMASK(7, 4)
|
||||
|
||||
#define ZL_REG_REF_ESYNC_DIV ZL_REG(10, 0x30, 4)
|
||||
#define ZL_REF_ESYNC_DIV_1HZ 0
|
||||
|
||||
@ -22,40 +22,25 @@ static int zl3073x_spi_probe(struct spi_device *spi)
|
||||
return dev_err_probe(dev, PTR_ERR(zldev->regmap),
|
||||
"Failed to initialize regmap\n");
|
||||
|
||||
return zl3073x_dev_probe(zldev, spi_get_device_match_data(spi));
|
||||
return zl3073x_dev_probe(zldev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id zl3073x_spi_id[] = {
|
||||
{
|
||||
.name = "zl30731",
|
||||
.driver_data = (kernel_ulong_t)&zl30731_chip_info
|
||||
},
|
||||
{
|
||||
.name = "zl30732",
|
||||
.driver_data = (kernel_ulong_t)&zl30732_chip_info,
|
||||
},
|
||||
{
|
||||
.name = "zl30733",
|
||||
.driver_data = (kernel_ulong_t)&zl30733_chip_info,
|
||||
},
|
||||
{
|
||||
.name = "zl30734",
|
||||
.driver_data = (kernel_ulong_t)&zl30734_chip_info,
|
||||
},
|
||||
{
|
||||
.name = "zl30735",
|
||||
.driver_data = (kernel_ulong_t)&zl30735_chip_info,
|
||||
},
|
||||
{ "zl30731" },
|
||||
{ "zl30732" },
|
||||
{ "zl30733" },
|
||||
{ "zl30734" },
|
||||
{ "zl30735" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, zl3073x_spi_id);
|
||||
|
||||
static const struct of_device_id zl3073x_spi_of_match[] = {
|
||||
{ .compatible = "microchip,zl30731", .data = &zl30731_chip_info },
|
||||
{ .compatible = "microchip,zl30732", .data = &zl30732_chip_info },
|
||||
{ .compatible = "microchip,zl30733", .data = &zl30733_chip_info },
|
||||
{ .compatible = "microchip,zl30734", .data = &zl30734_chip_info },
|
||||
{ .compatible = "microchip,zl30735", .data = &zl30735_chip_info },
|
||||
{ .compatible = "microchip,zl30731" },
|
||||
{ .compatible = "microchip,zl30732" },
|
||||
{ .compatible = "microchip,zl30733" },
|
||||
{ .compatible = "microchip,zl30734" },
|
||||
{ .compatible = "microchip,zl30735" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zl3073x_spi_of_match);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "regs.h"
|
||||
@ -20,11 +21,13 @@ struct zl3073x_dev;
|
||||
* @ctrl: synth control
|
||||
*/
|
||||
struct zl3073x_synth {
|
||||
u32 freq_mult;
|
||||
u16 freq_base;
|
||||
u16 freq_m;
|
||||
u16 freq_n;
|
||||
u8 ctrl;
|
||||
struct_group(inv, /* Invariants */
|
||||
u32 freq_mult;
|
||||
u16 freq_base;
|
||||
u16 freq_m;
|
||||
u16 freq_n;
|
||||
u8 ctrl;
|
||||
);
|
||||
};
|
||||
|
||||
int zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 synth_id);
|
||||
@ -32,9 +35,6 @@ int zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 synth_id);
|
||||
const struct zl3073x_synth *zl3073x_synth_state_get(struct zl3073x_dev *zldev,
|
||||
u8 synth_id);
|
||||
|
||||
int zl3073x_synth_state_set(struct zl3073x_dev *zldev, u8 synth_id,
|
||||
const struct zl3073x_synth *synth);
|
||||
|
||||
/**
|
||||
* zl3073x_synth_dpll_get - get DPLL ID the synth is driven by
|
||||
* @synth: pointer to synth state
|
||||
|
||||
@ -1655,7 +1655,7 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state->dsc.compression_enable = true;
|
||||
intel_dsc_enable_on_crtc(crtc_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4639,7 +4639,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state->fec_enable = limits->force_fec_pipes & BIT(crtc->pipe);
|
||||
crtc_state->dsc.compression_enabled_on_link = limits->link_dsc_pipes & BIT(crtc->pipe);
|
||||
crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
|
||||
|
||||
if (crtc_state->pipe_bpp > fxp_q4_to_int(crtc_state->max_link_bpp_x16)) {
|
||||
|
||||
@ -946,6 +946,12 @@ struct intel_csc_matrix {
|
||||
u16 postoff[3];
|
||||
};
|
||||
|
||||
enum intel_panel_replay_dsc_support {
|
||||
INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED,
|
||||
INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY,
|
||||
INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE,
|
||||
};
|
||||
|
||||
struct intel_crtc_state {
|
||||
/*
|
||||
* uapi (drm) state. This is the software state shown to userspace.
|
||||
@ -1124,6 +1130,8 @@ struct intel_crtc_state {
|
||||
bool has_panel_replay;
|
||||
bool wm_level_disabled;
|
||||
bool pkg_c_latency_used;
|
||||
/* Only used for state verification. */
|
||||
enum intel_panel_replay_dsc_support panel_replay_dsc_support;
|
||||
u32 dc3co_exitline;
|
||||
u16 su_y_granularity;
|
||||
u8 active_non_psr_pipes;
|
||||
@ -1268,6 +1276,8 @@ struct intel_crtc_state {
|
||||
|
||||
/* Display Stream compression state */
|
||||
struct {
|
||||
/* Only used for state computation, not read out from the HW. */
|
||||
bool compression_enabled_on_link;
|
||||
bool compression_enable;
|
||||
int num_streams;
|
||||
/* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */
|
||||
@ -1679,6 +1689,7 @@ struct intel_psr {
|
||||
bool source_panel_replay_support;
|
||||
bool sink_panel_replay_support;
|
||||
bool sink_panel_replay_su_support;
|
||||
enum intel_panel_replay_dsc_support sink_panel_replay_dsc_support;
|
||||
bool panel_replay_enabled;
|
||||
u32 dc3co_exitline;
|
||||
u32 dc3co_exit_delay;
|
||||
|
||||
@ -2340,24 +2340,29 @@ static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_dp_fec_compute_config(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *crtc_state)
|
||||
/*
|
||||
* Return whether FEC must be enabled for 8b10b SST or MST links. On 128b132b
|
||||
* links FEC is always enabled implicitly by the HW, so this function returns
|
||||
* false for that case.
|
||||
*/
|
||||
bool intel_dp_needs_8b10b_fec(const struct intel_crtc_state *crtc_state,
|
||||
bool dsc_enabled_on_crtc)
|
||||
{
|
||||
if (intel_dp_is_uhbr(crtc_state))
|
||||
return false;
|
||||
|
||||
if (crtc_state->fec_enable)
|
||||
return;
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Though eDP v1.5 supports FEC with DSC, unlike DP, it is optional.
|
||||
* Since, FEC is a bandwidth overhead, continue to not enable it for
|
||||
* eDP. Until, there is a good reason to do so.
|
||||
*/
|
||||
if (intel_dp_is_edp(intel_dp))
|
||||
return;
|
||||
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
|
||||
return false;
|
||||
|
||||
if (intel_dp_is_uhbr(crtc_state))
|
||||
return;
|
||||
|
||||
crtc_state->fec_enable = true;
|
||||
return dsc_enabled_on_crtc || intel_dsc_enabled_on_link(crtc_state);
|
||||
}
|
||||
|
||||
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
||||
@ -2375,7 +2380,11 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
||||
bool is_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST);
|
||||
int ret;
|
||||
|
||||
intel_dp_fec_compute_config(intel_dp, pipe_config);
|
||||
/*
|
||||
* FIXME: set the FEC enabled state once pipe_config->port_clock is
|
||||
* already known, so the UHBR/non-UHBR mode can be determined.
|
||||
*/
|
||||
pipe_config->fec_enable = intel_dp_needs_8b10b_fec(pipe_config, true);
|
||||
|
||||
if (!intel_dp_dsc_supports_format(connector, pipe_config->output_format))
|
||||
return -EINVAL;
|
||||
@ -2450,7 +2459,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
pipe_config->dsc.compression_enable = true;
|
||||
intel_dsc_enable_on_crtc(pipe_config);
|
||||
|
||||
drm_dbg_kms(display->drm, "DP DSC computed with Input Bpp = %d "
|
||||
"Compressed Bpp = " FXP_Q4_FMT " Slice Count = %d\n",
|
||||
pipe_config->pipe_bpp,
|
||||
@ -5921,6 +5931,8 @@ intel_dp_detect(struct drm_connector *_connector,
|
||||
memset(connector->dp.dsc_dpcd, 0, sizeof(connector->dp.dsc_dpcd));
|
||||
intel_dp->psr.sink_panel_replay_support = false;
|
||||
intel_dp->psr.sink_panel_replay_su_support = false;
|
||||
intel_dp->psr.sink_panel_replay_dsc_support =
|
||||
INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED;
|
||||
|
||||
intel_dp_mst_disconnect(intel_dp);
|
||||
|
||||
|
||||
@ -72,6 +72,8 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder);
|
||||
int intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
struct drm_connector_state *conn_state);
|
||||
bool intel_dp_needs_8b10b_fec(const struct intel_crtc_state *crtc_state,
|
||||
bool dsc_enabled_on_crtc);
|
||||
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
struct drm_connector_state *conn_state,
|
||||
|
||||
@ -293,12 +293,15 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
|
||||
mst_stream_update_slots(crtc_state, mst_state);
|
||||
}
|
||||
|
||||
if (dsc) {
|
||||
if (!intel_dp_supports_fec(intel_dp, connector, crtc_state))
|
||||
return -EINVAL;
|
||||
|
||||
crtc_state->fec_enable = !intel_dp_is_uhbr(crtc_state);
|
||||
}
|
||||
/*
|
||||
* NOTE: The following must reset crtc_state->fec_enable for UHBR/DSC
|
||||
* after it was set by intel_dp_dsc_compute_config() ->
|
||||
* intel_dp_needs_8b10b_fec().
|
||||
*/
|
||||
crtc_state->fec_enable = intel_dp_needs_8b10b_fec(crtc_state, dsc);
|
||||
if (crtc_state->fec_enable &&
|
||||
!intel_dp_supports_fec(intel_dp, connector, crtc_state))
|
||||
return -EINVAL;
|
||||
|
||||
max_dpt_bpp_x16 = fxp_q4_from_int(intel_dp_mst_max_dpt_bpp(crtc_state, dsc));
|
||||
if (max_dpt_bpp_x16 && max_bpp_x16 > max_dpt_bpp_x16) {
|
||||
@ -811,14 +814,14 @@ static u8 get_pipes_downstream_of_mst_port(struct intel_atomic_state *state,
|
||||
return mask;
|
||||
}
|
||||
|
||||
static int intel_dp_mst_check_fec_change(struct intel_atomic_state *state,
|
||||
static int intel_dp_mst_check_dsc_change(struct intel_atomic_state *state,
|
||||
struct drm_dp_mst_topology_mgr *mst_mgr,
|
||||
struct intel_link_bw_limits *limits)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct intel_crtc *crtc;
|
||||
u8 mst_pipe_mask;
|
||||
u8 fec_pipe_mask = 0;
|
||||
u8 dsc_pipe_mask = 0;
|
||||
int ret;
|
||||
|
||||
mst_pipe_mask = get_pipes_downstream_of_mst_port(state, mst_mgr, NULL);
|
||||
@ -831,16 +834,16 @@ static int intel_dp_mst_check_fec_change(struct intel_atomic_state *state,
|
||||
if (drm_WARN_ON(display->drm, !crtc_state))
|
||||
return -EINVAL;
|
||||
|
||||
if (crtc_state->fec_enable)
|
||||
fec_pipe_mask |= BIT(crtc->pipe);
|
||||
if (intel_dsc_enabled_on_link(crtc_state))
|
||||
dsc_pipe_mask |= BIT(crtc->pipe);
|
||||
}
|
||||
|
||||
if (!fec_pipe_mask || mst_pipe_mask == fec_pipe_mask)
|
||||
if (!dsc_pipe_mask || mst_pipe_mask == dsc_pipe_mask)
|
||||
return 0;
|
||||
|
||||
limits->force_fec_pipes |= mst_pipe_mask;
|
||||
limits->link_dsc_pipes |= mst_pipe_mask;
|
||||
|
||||
ret = intel_modeset_pipes_in_mask_early(state, "MST FEC",
|
||||
ret = intel_modeset_pipes_in_mask_early(state, "MST DSC",
|
||||
mst_pipe_mask);
|
||||
|
||||
return ret ? : -EAGAIN;
|
||||
@ -894,7 +897,7 @@ int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
|
||||
int i;
|
||||
|
||||
for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
|
||||
ret = intel_dp_mst_check_fec_change(state, mgr, limits);
|
||||
ret = intel_dp_mst_check_dsc_change(state, mgr, limits);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "intel_dp_tunnel.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_link_bw.h"
|
||||
#include "intel_vdsc.h"
|
||||
|
||||
static int get_forced_link_bpp_x16(struct intel_atomic_state *state,
|
||||
const struct intel_crtc *crtc)
|
||||
@ -55,7 +56,7 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
enum pipe pipe;
|
||||
|
||||
limits->force_fec_pipes = 0;
|
||||
limits->link_dsc_pipes = 0;
|
||||
limits->bpp_limit_reached_pipes = 0;
|
||||
for_each_pipe(display, pipe) {
|
||||
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
|
||||
@ -65,8 +66,8 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
|
||||
|
||||
if (state->base.duplicated && crtc_state) {
|
||||
limits->max_bpp_x16[pipe] = crtc_state->max_link_bpp_x16;
|
||||
if (crtc_state->fec_enable)
|
||||
limits->force_fec_pipes |= BIT(pipe);
|
||||
if (intel_dsc_enabled_on_link(crtc_state))
|
||||
limits->link_dsc_pipes |= BIT(pipe);
|
||||
} else {
|
||||
limits->max_bpp_x16[pipe] = INT_MAX;
|
||||
}
|
||||
@ -265,10 +266,10 @@ assert_link_limit_change_valid(struct intel_display *display,
|
||||
bool bpps_changed = false;
|
||||
enum pipe pipe;
|
||||
|
||||
/* FEC can't be forced off after it was forced on. */
|
||||
/* DSC can't be disabled after it was enabled. */
|
||||
if (drm_WARN_ON(display->drm,
|
||||
(old_limits->force_fec_pipes & new_limits->force_fec_pipes) !=
|
||||
old_limits->force_fec_pipes))
|
||||
(old_limits->link_dsc_pipes & new_limits->link_dsc_pipes) !=
|
||||
old_limits->link_dsc_pipes))
|
||||
return false;
|
||||
|
||||
for_each_pipe(display, pipe) {
|
||||
@ -286,8 +287,8 @@ assert_link_limit_change_valid(struct intel_display *display,
|
||||
/* At least one limit must change. */
|
||||
if (drm_WARN_ON(display->drm,
|
||||
!bpps_changed &&
|
||||
new_limits->force_fec_pipes ==
|
||||
old_limits->force_fec_pipes))
|
||||
new_limits->link_dsc_pipes ==
|
||||
old_limits->link_dsc_pipes))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@ -15,7 +15,7 @@ struct intel_connector;
|
||||
struct intel_crtc_state;
|
||||
|
||||
struct intel_link_bw_limits {
|
||||
u8 force_fec_pipes;
|
||||
u8 link_dsc_pipes;
|
||||
u8 bpp_limit_reached_pipes;
|
||||
/* in 1/16 bpp units */
|
||||
int max_bpp_x16[I915_MAX_PIPES];
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_alpm.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_crtc.h"
|
||||
@ -50,6 +51,7 @@
|
||||
#include "intel_snps_phy.h"
|
||||
#include "intel_step.h"
|
||||
#include "intel_vblank.h"
|
||||
#include "intel_vdsc.h"
|
||||
#include "intel_vrr.h"
|
||||
#include "skl_universal_plane.h"
|
||||
|
||||
@ -580,6 +582,44 @@ exit:
|
||||
intel_dp->psr.su_y_granularity = y;
|
||||
}
|
||||
|
||||
static enum intel_panel_replay_dsc_support
|
||||
compute_pr_dsc_support(struct intel_dp *intel_dp)
|
||||
{
|
||||
u8 pr_dsc_mode;
|
||||
u8 val;
|
||||
|
||||
val = intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)];
|
||||
pr_dsc_mode = REG_FIELD_GET8(DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK, val);
|
||||
|
||||
switch (pr_dsc_mode) {
|
||||
case DP_DSC_DECODE_CAPABILITY_IN_PR_FULL_FRAME_ONLY:
|
||||
return INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY;
|
||||
case DP_DSC_DECODE_CAPABILITY_IN_PR_SUPPORTED:
|
||||
return INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE;
|
||||
default:
|
||||
MISSING_CASE(pr_dsc_mode);
|
||||
fallthrough;
|
||||
case DP_DSC_DECODE_CAPABILITY_IN_PR_NOT_SUPPORTED:
|
||||
case DP_DSC_DECODE_CAPABILITY_IN_PR_RESERVED:
|
||||
return INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *panel_replay_dsc_support_str(enum intel_panel_replay_dsc_support dsc_support)
|
||||
{
|
||||
switch (dsc_support) {
|
||||
case INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED:
|
||||
return "not supported";
|
||||
case INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY:
|
||||
return "full frame only";
|
||||
case INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE:
|
||||
return "selective update";
|
||||
default:
|
||||
MISSING_CASE(dsc_support);
|
||||
return "n/a";
|
||||
};
|
||||
}
|
||||
|
||||
static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
@ -619,10 +659,13 @@ static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
|
||||
DP_PANEL_REPLAY_SU_SUPPORT)
|
||||
intel_dp->psr.sink_panel_replay_su_support = true;
|
||||
|
||||
intel_dp->psr.sink_panel_replay_dsc_support = compute_pr_dsc_support(intel_dp);
|
||||
|
||||
drm_dbg_kms(display->drm,
|
||||
"Panel replay %sis supported by panel\n",
|
||||
"Panel replay %sis supported by panel (in DSC mode: %s)\n",
|
||||
intel_dp->psr.sink_panel_replay_su_support ?
|
||||
"selective_update " : "");
|
||||
"selective_update " : "",
|
||||
panel_replay_dsc_support_str(intel_dp->psr.sink_panel_replay_dsc_support));
|
||||
}
|
||||
|
||||
static void _psr_init_dpcd(struct intel_dp *intel_dp)
|
||||
@ -1534,9 +1577,21 @@ static bool intel_sel_update_config_valid(struct intel_dp *intel_dp,
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
if (crtc_state->has_panel_replay && (DISPLAY_VER(display) < 14 ||
|
||||
!intel_dp->psr.sink_panel_replay_su_support))
|
||||
goto unsupported;
|
||||
if (crtc_state->has_panel_replay) {
|
||||
if (DISPLAY_VER(display) < 14)
|
||||
goto unsupported;
|
||||
|
||||
if (!intel_dp->psr.sink_panel_replay_su_support)
|
||||
goto unsupported;
|
||||
|
||||
if (intel_dsc_enabled_on_link(crtc_state) &&
|
||||
intel_dp->psr.sink_panel_replay_dsc_support !=
|
||||
INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"Selective update with Panel Replay not enabled because it's not supported with DSC\n");
|
||||
goto unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
if (crtc_state->crc_enabled) {
|
||||
drm_dbg_kms(display->drm,
|
||||
@ -1613,6 +1668,14 @@ _panel_replay_compute_config(struct intel_dp *intel_dp,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (intel_dsc_enabled_on_link(crtc_state) &&
|
||||
intel_dp->psr.sink_panel_replay_dsc_support ==
|
||||
INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"Panel Replay not enabled because it's not supported with DSC\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!intel_dp_is_edp(intel_dp))
|
||||
return true;
|
||||
|
||||
@ -1693,6 +1756,8 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only used for state verification. */
|
||||
crtc_state->panel_replay_dsc_support = intel_dp->psr.sink_panel_replay_dsc_support;
|
||||
crtc_state->has_panel_replay = _panel_replay_compute_config(intel_dp,
|
||||
crtc_state,
|
||||
conn_state);
|
||||
@ -2950,6 +3015,20 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
verify_panel_replay_dsc_state(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
|
||||
if (!crtc_state->has_panel_replay)
|
||||
return;
|
||||
|
||||
drm_WARN_ON(display->drm,
|
||||
intel_dsc_enabled_on_link(crtc_state) &&
|
||||
crtc_state->panel_replay_dsc_support ==
|
||||
INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
void intel_psr_post_plane_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
@ -2961,6 +3040,8 @@ void intel_psr_post_plane_update(struct intel_atomic_state *state,
|
||||
if (!crtc_state->has_psr)
|
||||
return;
|
||||
|
||||
verify_panel_replay_dsc_state(crtc_state);
|
||||
|
||||
for_each_intel_encoder_mask_with_psr(state->base.dev, encoder,
|
||||
crtc_state->uapi.encoder_mask) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
@ -3990,6 +4071,8 @@ static void intel_psr_sink_capability(struct intel_dp *intel_dp,
|
||||
seq_printf(m, ", Panel Replay = %s", str_yes_no(psr->sink_panel_replay_support));
|
||||
seq_printf(m, ", Panel Replay Selective Update = %s",
|
||||
str_yes_no(psr->sink_panel_replay_su_support));
|
||||
seq_printf(m, ", Panel Replay DSC support = %s",
|
||||
panel_replay_dsc_support_str(psr->sink_panel_replay_dsc_support));
|
||||
if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
|
||||
DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)
|
||||
seq_printf(m, " (Early Transport)");
|
||||
|
||||
@ -372,6 +372,22 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void intel_dsc_enable_on_crtc(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
crtc_state->dsc.compression_enabled_on_link = true;
|
||||
crtc_state->dsc.compression_enable = true;
|
||||
}
|
||||
|
||||
bool intel_dsc_enabled_on_link(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
|
||||
drm_WARN_ON(display->drm, crtc_state->dsc.compression_enable &&
|
||||
!crtc_state->dsc.compression_enabled_on_link);
|
||||
|
||||
return crtc_state->dsc.compression_enabled_on_link;
|
||||
}
|
||||
|
||||
enum intel_display_power_domain
|
||||
intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
|
||||
{
|
||||
|
||||
@ -20,6 +20,8 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
|
||||
void intel_dsc_enable(const struct intel_crtc_state *crtc_state);
|
||||
void intel_dsc_disable(const struct intel_crtc_state *crtc_state);
|
||||
int intel_dsc_compute_params(struct intel_crtc_state *pipe_config);
|
||||
void intel_dsc_enable_on_crtc(struct intel_crtc_state *crtc_state);
|
||||
bool intel_dsc_enabled_on_link(const struct intel_crtc_state *crtc_state);
|
||||
void intel_dsc_get_config(struct intel_crtc_state *crtc_state);
|
||||
enum intel_display_power_domain
|
||||
intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
@ -12,7 +13,7 @@
|
||||
void mgag200_bmc_stop_scanout(struct mga_device *mdev)
|
||||
{
|
||||
u8 tmp;
|
||||
int iter_max;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* 1 - The first step is to inform the BMC of an upcoming mode
|
||||
@ -42,30 +43,22 @@ void mgag200_bmc_stop_scanout(struct mga_device *mdev)
|
||||
|
||||
/*
|
||||
* 3a- The third step is to verify if there is an active scan.
|
||||
* We are waiting for a 0 on remhsyncsts <XSPAREREG<0>).
|
||||
* We are waiting for a 0 on remhsyncsts (<XSPAREREG<0>).
|
||||
*/
|
||||
iter_max = 300;
|
||||
while (!(tmp & 0x1) && iter_max) {
|
||||
WREG8(DAC_INDEX, MGA1064_SPAREREG);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
udelay(1000);
|
||||
iter_max--;
|
||||
}
|
||||
ret = read_poll_timeout(RREG_DAC, tmp, !(tmp & 0x1),
|
||||
1000, 300000, false,
|
||||
MGA1064_SPAREREG);
|
||||
if (ret == -ETIMEDOUT)
|
||||
return;
|
||||
|
||||
/*
|
||||
* 3b- This step occurs only if the remove is actually
|
||||
* 3b- This step occurs only if the remote BMC is actually
|
||||
* scanning. We are waiting for the end of the frame which is
|
||||
* a 1 on remvsyncsts (XSPAREREG<1>)
|
||||
*/
|
||||
if (iter_max) {
|
||||
iter_max = 300;
|
||||
while ((tmp & 0x2) && iter_max) {
|
||||
WREG8(DAC_INDEX, MGA1064_SPAREREG);
|
||||
tmp = RREG8(DAC_DATA);
|
||||
udelay(1000);
|
||||
iter_max--;
|
||||
}
|
||||
}
|
||||
(void)read_poll_timeout(RREG_DAC, tmp, (tmp & 0x2),
|
||||
1000, 300000, false,
|
||||
MGA1064_SPAREREG);
|
||||
}
|
||||
|
||||
void mgag200_bmc_start_scanout(struct mga_device *mdev)
|
||||
|
||||
@ -111,6 +111,12 @@
|
||||
#define DAC_INDEX 0x3c00
|
||||
#define DAC_DATA 0x3c0a
|
||||
|
||||
#define RREG_DAC(reg) \
|
||||
({ \
|
||||
WREG8(DAC_INDEX, reg); \
|
||||
RREG8(DAC_DATA); \
|
||||
}) \
|
||||
|
||||
#define WREG_DAC(reg, v) \
|
||||
do { \
|
||||
WREG8(DAC_INDEX, reg); \
|
||||
|
||||
@ -1208,10 +1208,20 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
|
||||
|
||||
switch (data[0]) {
|
||||
case 0x04:
|
||||
if (len < 32) {
|
||||
dev_warn(wacom->pen_input->dev.parent,
|
||||
"Report 0x04 too short: %zu bytes\n", len);
|
||||
break;
|
||||
}
|
||||
wacom_intuos_bt_process_data(wacom, data + i);
|
||||
i += 10;
|
||||
fallthrough;
|
||||
case 0x03:
|
||||
if (i == 1 && len < 22) {
|
||||
dev_warn(wacom->pen_input->dev.parent,
|
||||
"Report 0x03 too short: %zu bytes\n", len);
|
||||
break;
|
||||
}
|
||||
wacom_intuos_bt_process_data(wacom, data + i);
|
||||
i += 10;
|
||||
wacom_intuos_bt_process_data(wacom, data + i);
|
||||
|
||||
@ -221,13 +221,11 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
|
||||
|
||||
err = ib_umem_dmabuf_map_pages(umem_dmabuf);
|
||||
if (err)
|
||||
goto err_unpin;
|
||||
goto err_release;
|
||||
dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
|
||||
|
||||
return umem_dmabuf;
|
||||
|
||||
err_unpin:
|
||||
dma_buf_unpin(umem_dmabuf->attach);
|
||||
err_release:
|
||||
dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
|
||||
ib_umem_release(&umem_dmabuf->umem);
|
||||
|
||||
@ -170,6 +170,9 @@ static int map_cc_config_offset_gen0_ext0(u32 offset, struct bnxt_qplib_cc_param
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
|
||||
*val = ccparam->tcp_cp;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
|
||||
*val = ccparam->inact_th;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -203,7 +206,7 @@ static ssize_t bnxt_re_cc_config_get(struct file *filp, char __user *buffer,
|
||||
return simple_read_from_buffer(buffer, usr_buf_len, ppos, (u8 *)(buf), rc);
|
||||
}
|
||||
|
||||
static void bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
|
||||
static int bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
|
||||
{
|
||||
u32 modify_mask;
|
||||
|
||||
@ -247,7 +250,9 @@ static void bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offs
|
||||
ccparam->tcp_cp = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TX_QUEUE:
|
||||
return -EOPNOTSUPP;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
|
||||
ccparam->inact_th = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TIME_PER_PHASE:
|
||||
ccparam->time_pph = val;
|
||||
@ -258,17 +263,20 @@ static void bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offs
|
||||
}
|
||||
|
||||
ccparam->mask = modify_mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_re_configure_cc(struct bnxt_re_dev *rdev, u32 gen_ext, u32 offset, u32 val)
|
||||
{
|
||||
struct bnxt_qplib_cc_param ccparam = { };
|
||||
int rc;
|
||||
|
||||
/* Supporting only Gen 0 now */
|
||||
if (gen_ext == CC_CONFIG_GEN0_EXT0)
|
||||
bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
|
||||
else
|
||||
return -EINVAL;
|
||||
if (gen_ext != CC_CONFIG_GEN0_EXT0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rc = bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
bnxt_qplib_modify_cc(&rdev->qplib_res, &ccparam);
|
||||
return 0;
|
||||
|
||||
@ -4746,7 +4746,7 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
|
||||
return err;
|
||||
|
||||
err = uverbs_copy_to(attrs, BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
|
||||
&offset, sizeof(length));
|
||||
&offset, sizeof(offset));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@ -1113,7 +1113,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
||||
qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_FORCE_COMPLETION;
|
||||
if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE)
|
||||
qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_VARIABLE_SIZED_WQE_ENABLED;
|
||||
if (_is_ext_stats_supported(res->dattr->dev_cap_flags) && !res->is_vf)
|
||||
if (bnxt_ext_stats_supported(res->cctx, res->dattr->dev_cap_flags, res->is_vf))
|
||||
qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_EXT_STATS_ENABLED;
|
||||
|
||||
req.qp_flags = cpu_to_le32(qp_flags);
|
||||
@ -1750,9 +1750,9 @@ static void bnxt_qplib_fill_psn_search(struct bnxt_qplib_qp *qp,
|
||||
}
|
||||
}
|
||||
|
||||
static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
|
||||
struct bnxt_qplib_swqe *wqe,
|
||||
u16 *idx)
|
||||
static unsigned int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
|
||||
struct bnxt_qplib_swqe *wqe,
|
||||
u32 *idx)
|
||||
{
|
||||
struct bnxt_qplib_hwq *hwq;
|
||||
int len, t_len, offt;
|
||||
@ -1769,7 +1769,7 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
|
||||
il_src = (void *)wqe->sg_list[indx].addr;
|
||||
t_len += len;
|
||||
if (t_len > qp->max_inline_data)
|
||||
return -ENOMEM;
|
||||
return BNXT_RE_INVAL_MSG_SIZE;
|
||||
while (len) {
|
||||
if (pull_dst) {
|
||||
pull_dst = false;
|
||||
@ -1795,9 +1795,9 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
|
||||
return t_len;
|
||||
}
|
||||
|
||||
static u32 bnxt_qplib_put_sges(struct bnxt_qplib_hwq *hwq,
|
||||
struct bnxt_qplib_sge *ssge,
|
||||
u16 nsge, u16 *idx)
|
||||
static unsigned int bnxt_qplib_put_sges(struct bnxt_qplib_hwq *hwq,
|
||||
struct bnxt_qplib_sge *ssge,
|
||||
u32 nsge, u32 *idx)
|
||||
{
|
||||
struct sq_sge *dsge;
|
||||
int indx, len = 0;
|
||||
@ -1878,14 +1878,12 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
|
||||
struct bnxt_qplib_hwq *hwq;
|
||||
struct bnxt_qplib_swq *swq;
|
||||
bool sch_handler = false;
|
||||
u32 wqe_idx, slots, idx;
|
||||
u16 wqe_sz, qdf = 0;
|
||||
bool msn_update;
|
||||
void *base_hdr;
|
||||
void *ext_hdr;
|
||||
__le32 temp32;
|
||||
u32 wqe_idx;
|
||||
u32 slots;
|
||||
u16 idx;
|
||||
|
||||
hwq = &sq->hwq;
|
||||
if (qp->state != CMDQ_MODIFY_QP_NEW_STATE_RTS &&
|
||||
@ -1937,8 +1935,10 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
|
||||
else
|
||||
data_len = bnxt_qplib_put_sges(hwq, wqe->sg_list, wqe->num_sge,
|
||||
&idx);
|
||||
if (data_len < 0)
|
||||
goto queue_err;
|
||||
if (data_len > BNXT_RE_MAX_MSG_SIZE) {
|
||||
rc = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
/* Make sure we update MSN table only for wired wqes */
|
||||
msn_update = true;
|
||||
/* Specifics */
|
||||
@ -2139,8 +2139,8 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
|
||||
struct bnxt_qplib_hwq *hwq;
|
||||
struct bnxt_qplib_swq *swq;
|
||||
bool sch_handler = false;
|
||||
u16 wqe_sz, idx;
|
||||
u32 wqe_idx;
|
||||
u32 wqe_idx, idx;
|
||||
u16 wqe_sz;
|
||||
int rc = 0;
|
||||
|
||||
hwq = &rq->hwq;
|
||||
|
||||
@ -346,6 +346,9 @@ struct bnxt_qplib_qp {
|
||||
u8 tos_dscp;
|
||||
};
|
||||
|
||||
#define BNXT_RE_MAX_MSG_SIZE 0x80000000
|
||||
#define BNXT_RE_INVAL_MSG_SIZE 0xFFFFFFFF
|
||||
|
||||
#define BNXT_QPLIB_MAX_CQE_ENTRY_SIZE sizeof(struct cq_base)
|
||||
|
||||
#define CQE_CNT_PER_PG (PAGE_SIZE / BNXT_QPLIB_MAX_CQE_ENTRY_SIZE)
|
||||
|
||||
@ -160,7 +160,7 @@ static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
|
||||
wait_event_timeout(cmdq->waitq,
|
||||
!crsqe->is_in_used ||
|
||||
test_bit(ERR_DEVICE_DETACHED, &cmdq->flags),
|
||||
msecs_to_jiffies(rcfw->max_timeout * 1000));
|
||||
secs_to_jiffies(rcfw->max_timeout));
|
||||
|
||||
if (!crsqe->is_in_used)
|
||||
return 0;
|
||||
|
||||
@ -674,7 +674,7 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
|
||||
req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) <<
|
||||
CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) &
|
||||
CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK));
|
||||
req.access = (mr->access_flags & 0xFFFF);
|
||||
req.access = (mr->access_flags & BNXT_QPLIB_MR_ACCESS_MASK);
|
||||
req.va = cpu_to_le64(mr->va);
|
||||
req.key = cpu_to_le32(mr->lkey);
|
||||
if (_is_alloc_mr_unified(res->dattr->dev_cap_flags))
|
||||
@ -846,7 +846,12 @@ int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid,
|
||||
|
||||
req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS;
|
||||
req.resp_addr = cpu_to_le64(sbuf.dma_addr);
|
||||
req.function_id = cpu_to_le32(fid);
|
||||
if (bnxt_qplib_is_chip_gen_p7(rcfw->res->cctx) && rcfw->res->is_vf)
|
||||
req.function_id =
|
||||
cpu_to_le32(CMDQ_QUERY_ROCE_STATS_EXT_VF_VALID |
|
||||
(fid << CMDQ_QUERY_ROCE_STATS_EXT_VF_NUM_SFT));
|
||||
else
|
||||
req.function_id = cpu_to_le32(fid);
|
||||
req.flags = cpu_to_le16(CMDQ_QUERY_ROCE_STATS_EXT_FLAGS_FUNCTION_ID);
|
||||
|
||||
bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req),
|
||||
|
||||
@ -111,6 +111,7 @@ struct bnxt_qplib_mrw {
|
||||
struct bnxt_qplib_pd *pd;
|
||||
int type;
|
||||
u32 access_flags;
|
||||
#define BNXT_QPLIB_MR_ACCESS_MASK 0xFF
|
||||
#define BNXT_QPLIB_FR_PMR 0x80000000
|
||||
u32 lkey;
|
||||
u32 rkey;
|
||||
|
||||
@ -490,12 +490,20 @@ static int rebalance_children(struct shadow_spine *s,
|
||||
|
||||
if (le32_to_cpu(n->header.nr_entries) == 1) {
|
||||
struct dm_block *child;
|
||||
int is_shared;
|
||||
dm_block_t b = value64(n, 0);
|
||||
|
||||
r = dm_tm_block_is_shared(info->tm, b, &is_shared);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dm_tm_read_lock(info->tm, b, &btree_node_validator, &child);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (is_shared)
|
||||
inc_children(info->tm, dm_block_data(child), vt);
|
||||
|
||||
memcpy(n, dm_block_data(child),
|
||||
dm_bm_block_size(dm_tm_get_bm(info->tm)));
|
||||
|
||||
|
||||
@ -3014,6 +3014,19 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev)
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (!ethsw->sw_attr.num_ifs) {
|
||||
dev_err(dev, "DPSW device has no interfaces\n");
|
||||
err = -ENODEV;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (ethsw->sw_attr.num_ifs >= DPSW_MAX_IF) {
|
||||
dev_err(dev, "DPSW num_ifs %u exceeds max %u\n",
|
||||
ethsw->sw_attr.num_ifs, DPSW_MAX_IF);
|
||||
err = -EINVAL;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
err = dpsw_get_api_version(ethsw->mc_io, 0,
|
||||
ðsw->major,
|
||||
ðsw->minor);
|
||||
|
||||
@ -9030,7 +9030,6 @@ int i40e_open(struct net_device *netdev)
|
||||
TCP_FLAG_FIN |
|
||||
TCP_FLAG_CWR) >> 16);
|
||||
wr32(&pf->hw, I40E_GLLAN_TSOMSK_L, be32_to_cpu(TCP_FLAG_CWR) >> 16);
|
||||
udp_tunnel_get_rx_info(netdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -839,6 +839,28 @@ static inline void ice_tx_xsk_pool(struct ice_vsi *vsi, u16 qid)
|
||||
WRITE_ONCE(ring->xsk_pool, ice_get_xp_from_qid(vsi, qid));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_max_txq - return the maximum number of Tx queues for in a PF
|
||||
* @pf: PF structure
|
||||
*
|
||||
* Return: maximum number of Tx queues
|
||||
*/
|
||||
static inline int ice_get_max_txq(struct ice_pf *pf)
|
||||
{
|
||||
return min(num_online_cpus(), pf->hw.func_caps.common_cap.num_txq);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_max_rxq - return the maximum number of Rx queues for in a PF
|
||||
* @pf: PF structure
|
||||
*
|
||||
* Return: maximum number of Rx queues
|
||||
*/
|
||||
static inline int ice_get_max_rxq(struct ice_pf *pf)
|
||||
{
|
||||
return min(num_online_cpus(), pf->hw.func_caps.common_cap.num_rxq);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_main_vsi - Get the PF VSI
|
||||
* @pf: PF instance
|
||||
|
||||
@ -3756,24 +3756,6 @@ ice_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_max_txq - return the maximum number of Tx queues for in a PF
|
||||
* @pf: PF structure
|
||||
*/
|
||||
static int ice_get_max_txq(struct ice_pf *pf)
|
||||
{
|
||||
return min(num_online_cpus(), pf->hw.func_caps.common_cap.num_txq);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_max_rxq - return the maximum number of Rx queues for in a PF
|
||||
* @pf: PF structure
|
||||
*/
|
||||
static int ice_get_max_rxq(struct ice_pf *pf)
|
||||
{
|
||||
return min(num_online_cpus(), pf->hw.func_caps.common_cap.num_rxq);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_combined_cnt - return the current number of combined channels
|
||||
* @vsi: PF VSI pointer
|
||||
|
||||
@ -106,9 +106,10 @@ static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf,
|
||||
#define ICE_RDMA_AEQ_MSIX 1
|
||||
static int ice_get_default_msix_amount(struct ice_pf *pf)
|
||||
{
|
||||
return ICE_MIN_LAN_OICR_MSIX + num_online_cpus() +
|
||||
return ICE_MIN_LAN_OICR_MSIX + netif_get_num_default_rss_queues() +
|
||||
(test_bit(ICE_FLAG_FD_ENA, pf->flags) ? ICE_FDIR_MSIX : 0) +
|
||||
(ice_is_rdma_ena(pf) ? num_online_cpus() + ICE_RDMA_AEQ_MSIX : 0);
|
||||
(ice_is_rdma_ena(pf) ? netif_get_num_default_rss_queues() +
|
||||
ICE_RDMA_AEQ_MSIX : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -155,12 +155,14 @@ static void ice_vsi_set_num_desc(struct ice_vsi *vsi)
|
||||
|
||||
static u16 ice_get_rxq_count(struct ice_pf *pf)
|
||||
{
|
||||
return min(ice_get_avail_rxq_count(pf), num_online_cpus());
|
||||
return min(ice_get_avail_rxq_count(pf),
|
||||
netif_get_num_default_rss_queues());
|
||||
}
|
||||
|
||||
static u16 ice_get_txq_count(struct ice_pf *pf)
|
||||
{
|
||||
return min(ice_get_avail_txq_count(pf), num_online_cpus());
|
||||
return min(ice_get_avail_txq_count(pf),
|
||||
netif_get_num_default_rss_queues());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -909,13 +911,15 @@ static void ice_vsi_set_rss_params(struct ice_vsi *vsi)
|
||||
if (vsi->type == ICE_VSI_CHNL)
|
||||
vsi->rss_size = min_t(u16, vsi->num_rxq, max_rss_size);
|
||||
else
|
||||
vsi->rss_size = min_t(u16, num_online_cpus(),
|
||||
vsi->rss_size = min_t(u16,
|
||||
netif_get_num_default_rss_queues(),
|
||||
max_rss_size);
|
||||
vsi->rss_lut_type = ICE_LUT_PF;
|
||||
break;
|
||||
case ICE_VSI_SF:
|
||||
vsi->rss_table_size = ICE_LUT_VSI_SIZE;
|
||||
vsi->rss_size = min_t(u16, num_online_cpus(), max_rss_size);
|
||||
vsi->rss_size = min_t(u16, netif_get_num_default_rss_queues(),
|
||||
max_rss_size);
|
||||
vsi->rss_lut_type = ICE_LUT_VSI;
|
||||
break;
|
||||
case ICE_VSI_VF:
|
||||
|
||||
@ -4699,8 +4699,8 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
|
||||
struct net_device *netdev;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
|
||||
vsi->alloc_rxq);
|
||||
netdev = alloc_etherdev_mqs(sizeof(*np), ice_get_max_txq(vsi->back),
|
||||
ice_get_max_rxq(vsi->back));
|
||||
if (!netdev)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -9665,9 +9665,6 @@ int ice_open_internal(struct net_device *netdev)
|
||||
netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n",
|
||||
vsi->vsi_num, vsi->vsw->sw_id);
|
||||
|
||||
/* Update existing tunnels information */
|
||||
udp_tunnel_get_rx_info(netdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -300,7 +300,8 @@ static int mlx5_dpll_state_on_dpll_set(const struct dpll_pin *pin,
|
||||
|
||||
static int mlx5_dpll_ffo_get(const struct dpll_pin *pin, void *pin_priv,
|
||||
const struct dpll_device *dpll, void *dpll_priv,
|
||||
s64 *ffo, struct netlink_ext_ack *extack)
|
||||
struct dpll_ffo_param *ffo,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_dpll_synce_status synce_status;
|
||||
struct mlx5_dpll *mdpll = pin_priv;
|
||||
@ -309,10 +310,11 @@ static int mlx5_dpll_ffo_get(const struct dpll_pin *pin, void *pin_priv,
|
||||
err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status);
|
||||
if (err)
|
||||
return err;
|
||||
return mlx5_dpll_pin_ffo_get(&synce_status, ffo);
|
||||
return mlx5_dpll_pin_ffo_get(&synce_status, &ffo->ffo);
|
||||
}
|
||||
|
||||
static const struct dpll_pin_ops mlx5_dpll_pins_ops = {
|
||||
.supported_ffo = BIT(DPLL_FFO_PORT_RXTX_RATE),
|
||||
.direction_get = mlx5_dpll_pin_direction_get,
|
||||
.state_on_dpll_get = mlx5_dpll_state_on_dpll_get,
|
||||
.state_on_dpll_set = mlx5_dpll_state_on_dpll_set,
|
||||
|
||||
@ -1719,13 +1719,18 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
|
||||
if (ether_addr_equal(netdev->dev_addr, mac))
|
||||
return 0;
|
||||
|
||||
err = ionic_program_mac(lif, mac);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* Only program macs for virtual functions to avoid losing the permanent
|
||||
* Mac across warm reset/reboot.
|
||||
*/
|
||||
if (lif->ionic->pdev->is_virtfn) {
|
||||
err = ionic_program_mac(lif, mac);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (err > 0)
|
||||
netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n",
|
||||
__func__);
|
||||
if (err > 0)
|
||||
netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
err = eth_prepare_mac_addr_change(netdev, addr);
|
||||
if (err)
|
||||
|
||||
@ -1757,6 +1757,9 @@ static int netvsc_set_rxfh(struct net_device *dev,
|
||||
rxfh->hfunc != ETH_RSS_HASH_TOP)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!ndc->rx_table_sz)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rndis_dev = ndev->extension;
|
||||
if (rxfh->indir) {
|
||||
for (i = 0; i < ndc->rx_table_sz; i++)
|
||||
|
||||
@ -153,6 +153,11 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
||||
bphy_err(drvr, "invalid interface index: %u\n", ifevent->ifidx);
|
||||
return;
|
||||
}
|
||||
if (ifevent->bsscfgidx >= BRCMF_MAX_IFS) {
|
||||
bphy_err(drvr, "invalid bsscfg index: %u\n",
|
||||
ifevent->bsscfgidx);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[ifevent->bsscfgidx];
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -312,6 +312,7 @@ struct lpfc_defer_flogi_acc {
|
||||
u16 rx_id;
|
||||
u16 ox_id;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
};
|
||||
|
||||
#define LPFC_VMID_TIMER 300 /* timer interval in seconds */
|
||||
@ -634,7 +635,6 @@ struct lpfc_vport {
|
||||
#define FC_CT_RSPN_ID 0x8 /* RSPN_ID accepted by switch */
|
||||
#define FC_CT_RFT_ID 0x10 /* RFT_ID accepted by switch */
|
||||
#define FC_CT_RPRT_DEFER 0x20 /* Defer issuing FDMI RPRT */
|
||||
#define FC_CT_RSPNI_PNI 0x40 /* RSPNI_PNI accepted by switch */
|
||||
|
||||
struct list_head fc_nodes;
|
||||
spinlock_t fc_nodes_list_lock; /* spinlock for fc_nodes list */
|
||||
@ -662,12 +662,15 @@ struct lpfc_vport {
|
||||
uint32_t num_disc_nodes; /* in addition to hba_state */
|
||||
uint32_t gidft_inp; /* cnt of outstanding GID_FTs */
|
||||
|
||||
uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */
|
||||
uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */
|
||||
uint32_t fc_rscn_flush; /* flag use of fc_rscn_id_list */
|
||||
struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
|
||||
struct lpfc_name fc_nodename; /* fc nodename */
|
||||
struct lpfc_name fc_portname; /* fc portname */
|
||||
|
||||
struct lpfc_work_evt disc_timeout_evt;
|
||||
|
||||
struct timer_list fc_disctmo; /* Discovery rescue timer */
|
||||
uint8_t fc_ns_retry; /* retries for fabric nameserver */
|
||||
uint32_t fc_prli_sent; /* cntr for outstanding PRLIs */
|
||||
@ -742,6 +745,12 @@ struct lpfc_vport {
|
||||
struct lpfc_vmid_priority_info vmid_priority;
|
||||
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
struct dentry *debug_disc_trc;
|
||||
struct dentry *debug_nodelist;
|
||||
struct dentry *debug_nvmestat;
|
||||
struct dentry *debug_scsistat;
|
||||
struct dentry *debug_ioktime;
|
||||
struct dentry *debug_hdwqstat;
|
||||
struct dentry *vport_debugfs_root;
|
||||
struct lpfc_debugfs_trc *disc_trc;
|
||||
atomic_t disc_trc_cnt;
|
||||
@ -759,6 +768,7 @@ struct lpfc_vport {
|
||||
/* There is a single nvme instance per vport. */
|
||||
struct nvme_fc_local_port *localport;
|
||||
uint8_t nvmei_support; /* driver supports NVME Initiator */
|
||||
uint32_t last_fcp_wqidx;
|
||||
uint32_t rcv_flogi_cnt; /* How many unsol FLOGIs ACK'd. */
|
||||
};
|
||||
|
||||
@ -1051,6 +1061,8 @@ struct lpfc_hba {
|
||||
|
||||
struct lpfc_dmabuf hbqslimp;
|
||||
|
||||
uint16_t pci_cfg_value;
|
||||
|
||||
uint8_t fc_linkspeed; /* Link speed after last READ_LA */
|
||||
|
||||
uint32_t fc_eventTag; /* event tag for link attention */
|
||||
@ -1077,10 +1089,9 @@ struct lpfc_hba {
|
||||
|
||||
struct lpfc_stats fc_stat;
|
||||
|
||||
struct lpfc_nodelist fc_fcpnodev; /* nodelist entry for no device */
|
||||
uint32_t nport_event_cnt; /* timestamp for nlplist entry */
|
||||
|
||||
unsigned long pni; /* 64-bit Platform Name Identifier */
|
||||
|
||||
uint8_t wwnn[8];
|
||||
uint8_t wwpn[8];
|
||||
uint32_t RandomData[7];
|
||||
@ -1219,6 +1230,9 @@ struct lpfc_hba {
|
||||
uint32_t hbq_count; /* Count of configured HBQs */
|
||||
struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */
|
||||
|
||||
atomic_t fcp_qidx; /* next FCP WQ (RR Policy) */
|
||||
atomic_t nvme_qidx; /* next NVME WQ (RR Policy) */
|
||||
|
||||
phys_addr_t pci_bar0_map; /* Physical address for PCI BAR0 */
|
||||
phys_addr_t pci_bar1_map; /* Physical address for PCI BAR1 */
|
||||
phys_addr_t pci_bar2_map; /* Physical address for PCI BAR2 */
|
||||
@ -1335,9 +1349,30 @@ struct lpfc_hba {
|
||||
unsigned long last_ramp_down_time;
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
struct dentry *hba_debugfs_root;
|
||||
unsigned int debugfs_vport_count;
|
||||
atomic_t debugfs_vport_count;
|
||||
struct dentry *debug_multixri_pools;
|
||||
struct dentry *debug_hbqinfo;
|
||||
struct dentry *debug_dumpHostSlim;
|
||||
struct dentry *debug_dumpHBASlim;
|
||||
struct dentry *debug_InjErrLBA; /* LBA to inject errors at */
|
||||
struct dentry *debug_InjErrNPortID; /* NPortID to inject errors at */
|
||||
struct dentry *debug_InjErrWWPN; /* WWPN to inject errors at */
|
||||
struct dentry *debug_writeGuard; /* inject write guard_tag errors */
|
||||
struct dentry *debug_writeApp; /* inject write app_tag errors */
|
||||
struct dentry *debug_writeRef; /* inject write ref_tag errors */
|
||||
struct dentry *debug_readGuard; /* inject read guard_tag errors */
|
||||
struct dentry *debug_readApp; /* inject read app_tag errors */
|
||||
struct dentry *debug_readRef; /* inject read ref_tag errors */
|
||||
|
||||
struct dentry *debug_nvmeio_trc;
|
||||
struct lpfc_debugfs_nvmeio_trc *nvmeio_trc;
|
||||
struct dentry *debug_hdwqinfo;
|
||||
#ifdef LPFC_HDWQ_LOCK_STAT
|
||||
struct dentry *debug_lockstat;
|
||||
#endif
|
||||
struct dentry *debug_cgn_buffer;
|
||||
struct dentry *debug_rx_monitor;
|
||||
struct dentry *debug_ras_log;
|
||||
atomic_t nvmeio_trc_cnt;
|
||||
uint32_t nvmeio_trc_size;
|
||||
uint32_t nvmeio_trc_output_idx;
|
||||
@ -1354,10 +1389,19 @@ struct lpfc_hba {
|
||||
sector_t lpfc_injerr_lba;
|
||||
#define LPFC_INJERR_LBA_OFF (sector_t)(-1)
|
||||
|
||||
struct dentry *debug_slow_ring_trc;
|
||||
struct lpfc_debugfs_trc *slow_ring_trc;
|
||||
atomic_t slow_ring_trc_cnt;
|
||||
/* iDiag debugfs sub-directory */
|
||||
struct dentry *idiag_root;
|
||||
struct dentry *idiag_pci_cfg;
|
||||
struct dentry *idiag_bar_acc;
|
||||
struct dentry *idiag_que_info;
|
||||
struct dentry *idiag_que_acc;
|
||||
struct dentry *idiag_drb_acc;
|
||||
struct dentry *idiag_ctl_acc;
|
||||
struct dentry *idiag_mbx_acc;
|
||||
struct dentry *idiag_ext_acc;
|
||||
uint8_t lpfc_idiag_last_eq;
|
||||
#endif
|
||||
uint16_t nvmeio_trc_on;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -264,9 +264,9 @@ ct_free_mpvirt:
|
||||
ct_free_mp:
|
||||
kfree(mp);
|
||||
ct_exit:
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"6440 Unsol CT: Rsp err %d Data: x%lx\n",
|
||||
rc, vport->fc_flag);
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
||||
"6440 Unsol CT: Rsp err %d Data: x%lx\n",
|
||||
rc, vport->fc_flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,7 +313,7 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq)
|
||||
|
||||
mi_cmd = be16_to_cpu(ct_req->CommandResponse.bits.CmdRsp);
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"6442 MI Cmd: x%x Not Supported\n", mi_cmd);
|
||||
"6442 MI Cmd : x%x Not Supported\n", mi_cmd);
|
||||
lpfc_ct_reject_event(ndlp, ct_req,
|
||||
bf_get(wqe_ctxt_tag,
|
||||
&ctiocbq->wqe.xmit_els_rsp.wqe_com),
|
||||
@ -1742,28 +1742,6 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_cmpl_ct_cmd_rspni_pni(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_iocbq *rspiocb)
|
||||
{
|
||||
struct lpfc_vport *vport;
|
||||
struct lpfc_dmabuf *outp;
|
||||
struct lpfc_sli_ct_request *ctrsp;
|
||||
u32 ulp_status;
|
||||
|
||||
vport = cmdiocb->vport;
|
||||
ulp_status = get_job_ulpstatus(phba, rspiocb);
|
||||
|
||||
if (ulp_status == IOSTAT_SUCCESS) {
|
||||
outp = cmdiocb->rsp_dmabuf;
|
||||
ctrsp = (struct lpfc_sli_ct_request *)outp->virt;
|
||||
if (be16_to_cpu(ctrsp->CommandResponse.bits.CmdRsp) ==
|
||||
SLI_CT_RESPONSE_FS_ACC)
|
||||
vport->ct_flags |= FC_CT_RSPNI_PNI;
|
||||
}
|
||||
lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_cmpl_ct_cmd_da_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_iocbq *rspiocb)
|
||||
@ -1978,8 +1956,6 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
|
||||
bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_RSNN_NN)
|
||||
bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_RSPNI_PNI)
|
||||
bpl->tus.f.bdeSize = RSPNI_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_DA_ID)
|
||||
bpl->tus.f.bdeSize = DA_ID_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_RFF_ID)
|
||||
@ -2101,18 +2077,6 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
|
||||
CtReq->un.rsnn.symbname, size);
|
||||
cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
|
||||
break;
|
||||
case SLI_CTNS_RSPNI_PNI:
|
||||
vport->ct_flags &= ~FC_CT_RSPNI_PNI;
|
||||
CtReq->CommandResponse.bits.CmdRsp =
|
||||
cpu_to_be16(SLI_CTNS_RSPNI_PNI);
|
||||
CtReq->un.rspni.pni = cpu_to_be64(phba->pni);
|
||||
scnprintf(CtReq->un.rspni.symbname,
|
||||
sizeof(CtReq->un.rspni.symbname), "OS Host Name::%s",
|
||||
phba->os_host_name);
|
||||
CtReq->un.rspni.len = strnlen(CtReq->un.rspni.symbname,
|
||||
sizeof(CtReq->un.rspni.symbname));
|
||||
cmpl = lpfc_cmpl_ct_cmd_rspni_pni;
|
||||
break;
|
||||
case SLI_CTNS_DA_ID:
|
||||
/* Implement DA_ID Nameserver request */
|
||||
CtReq->CommandResponse.bits.CmdRsp =
|
||||
@ -2265,6 +2229,21 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
/* Look for a retryable error */
|
||||
if (ulp_status == IOSTAT_LOCAL_REJECT) {
|
||||
switch ((ulp_word4 & IOERR_PARAM_MASK)) {
|
||||
case IOERR_SLI_ABORTED:
|
||||
case IOERR_SLI_DOWN:
|
||||
/* Driver aborted this IO. No retry as error
|
||||
* is likely Offline->Online or some adapter
|
||||
* error. Recovery will try again, but if port
|
||||
* is not active there's no point to continue
|
||||
* issuing follow up FDMI commands.
|
||||
*/
|
||||
if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE)) {
|
||||
free_ndlp = cmdiocb->ndlp;
|
||||
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||
lpfc_nlp_put(free_ndlp);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case IOERR_ABORT_IN_PROGRESS:
|
||||
case IOERR_SEQUENCE_TIMEOUT:
|
||||
case IOERR_ILLEGAL_FRAME:
|
||||
@ -2290,9 +2269,6 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||
lpfc_nlp_put(free_ndlp);
|
||||
|
||||
if (ulp_status != IOSTAT_SUCCESS)
|
||||
return;
|
||||
|
||||
ndlp = lpfc_findnode_did(vport, FDMI_DID);
|
||||
if (!ndlp)
|
||||
return;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2007-2015 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -2373,117 +2373,93 @@ out:
|
||||
|
||||
static ssize_t
|
||||
lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
|
||||
size_t nbytes, loff_t *ppos)
|
||||
size_t nbytes, loff_t *ppos)
|
||||
{
|
||||
struct dentry *dent = file->f_path.dentry;
|
||||
struct lpfc_hba *phba = file->private_data;
|
||||
int kind = debugfs_get_aux_num(file);
|
||||
char cbuf[32] = {0};
|
||||
char cbuf[32];
|
||||
uint64_t tmp = 0;
|
||||
int cnt = 0;
|
||||
|
||||
switch (kind) {
|
||||
case writeGuard:
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
|
||||
phba->lpfc_injerr_wgrd_cnt);
|
||||
break;
|
||||
case writeApp:
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
|
||||
phba->lpfc_injerr_wapp_cnt);
|
||||
break;
|
||||
case writeRef:
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
|
||||
phba->lpfc_injerr_wref_cnt);
|
||||
break;
|
||||
case readGuard:
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
|
||||
phba->lpfc_injerr_rgrd_cnt);
|
||||
break;
|
||||
case readApp:
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
|
||||
phba->lpfc_injerr_rapp_cnt);
|
||||
break;
|
||||
case readRef:
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
|
||||
phba->lpfc_injerr_rref_cnt);
|
||||
break;
|
||||
case InjErrNPortID:
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "0x%06x\n",
|
||||
if (dent == phba->debug_writeGuard)
|
||||
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt);
|
||||
else if (dent == phba->debug_writeApp)
|
||||
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt);
|
||||
else if (dent == phba->debug_writeRef)
|
||||
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt);
|
||||
else if (dent == phba->debug_readGuard)
|
||||
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt);
|
||||
else if (dent == phba->debug_readApp)
|
||||
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt);
|
||||
else if (dent == phba->debug_readRef)
|
||||
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt);
|
||||
else if (dent == phba->debug_InjErrNPortID)
|
||||
cnt = scnprintf(cbuf, 32, "0x%06x\n",
|
||||
phba->lpfc_injerr_nportid);
|
||||
break;
|
||||
case InjErrWWPN:
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "0x%016llx\n",
|
||||
be64_to_cpu(phba->lpfc_injerr_wwpn.u.wwn_be));
|
||||
break;
|
||||
case InjErrLBA:
|
||||
if (phba->lpfc_injerr_lba == LPFC_INJERR_LBA_OFF)
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "off\n");
|
||||
else if (dent == phba->debug_InjErrWWPN) {
|
||||
memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name));
|
||||
tmp = cpu_to_be64(tmp);
|
||||
cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp);
|
||||
} else if (dent == phba->debug_InjErrLBA) {
|
||||
if (phba->lpfc_injerr_lba == (sector_t)(-1))
|
||||
cnt = scnprintf(cbuf, 32, "off\n");
|
||||
else
|
||||
cnt = scnprintf(cbuf, sizeof(cbuf), "0x%llx\n",
|
||||
(uint64_t)phba->lpfc_injerr_lba);
|
||||
break;
|
||||
default:
|
||||
lpfc_log_msg(phba, KERN_WARNING, LOG_INIT,
|
||||
"0547 Unknown debugfs error injection entry\n");
|
||||
break;
|
||||
}
|
||||
cnt = scnprintf(cbuf, 32, "0x%llx\n",
|
||||
(uint64_t) phba->lpfc_injerr_lba);
|
||||
} else
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"0547 Unknown debugfs error injection entry\n");
|
||||
|
||||
return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
|
||||
size_t nbytes, loff_t *ppos)
|
||||
size_t nbytes, loff_t *ppos)
|
||||
{
|
||||
struct dentry *dent = file->f_path.dentry;
|
||||
struct lpfc_hba *phba = file->private_data;
|
||||
int kind = debugfs_get_aux_num(file);
|
||||
char dstbuf[33] = {0};
|
||||
unsigned long long tmp;
|
||||
unsigned long size;
|
||||
char dstbuf[33];
|
||||
uint64_t tmp = 0;
|
||||
int size;
|
||||
|
||||
size = (nbytes < (sizeof(dstbuf) - 1)) ? nbytes : (sizeof(dstbuf) - 1);
|
||||
memset(dstbuf, 0, 33);
|
||||
size = (nbytes < 32) ? nbytes : 32;
|
||||
if (copy_from_user(dstbuf, buf, size))
|
||||
return -EFAULT;
|
||||
|
||||
if (kstrtoull(dstbuf, 0, &tmp)) {
|
||||
if (kind != InjErrLBA || !strstr(dstbuf, "off"))
|
||||
return -EINVAL;
|
||||
if (dent == phba->debug_InjErrLBA) {
|
||||
if ((dstbuf[0] == 'o') && (dstbuf[1] == 'f') &&
|
||||
(dstbuf[2] == 'f'))
|
||||
tmp = (uint64_t)(-1);
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
case writeGuard:
|
||||
if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp)))
|
||||
return -EINVAL;
|
||||
|
||||
if (dent == phba->debug_writeGuard)
|
||||
phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
|
||||
break;
|
||||
case writeApp:
|
||||
else if (dent == phba->debug_writeApp)
|
||||
phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
|
||||
break;
|
||||
case writeRef:
|
||||
else if (dent == phba->debug_writeRef)
|
||||
phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
|
||||
break;
|
||||
case readGuard:
|
||||
else if (dent == phba->debug_readGuard)
|
||||
phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp;
|
||||
break;
|
||||
case readApp:
|
||||
else if (dent == phba->debug_readApp)
|
||||
phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
|
||||
break;
|
||||
case readRef:
|
||||
else if (dent == phba->debug_readRef)
|
||||
phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
|
||||
break;
|
||||
case InjErrLBA:
|
||||
if (strstr(dstbuf, "off"))
|
||||
phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
|
||||
else
|
||||
phba->lpfc_injerr_lba = (sector_t)tmp;
|
||||
break;
|
||||
case InjErrNPortID:
|
||||
else if (dent == phba->debug_InjErrLBA)
|
||||
phba->lpfc_injerr_lba = (sector_t)tmp;
|
||||
else if (dent == phba->debug_InjErrNPortID)
|
||||
phba->lpfc_injerr_nportid = (uint32_t)(tmp & Mask_DID);
|
||||
break;
|
||||
case InjErrWWPN:
|
||||
phba->lpfc_injerr_wwpn.u.wwn_be = cpu_to_be64(tmp);
|
||||
break;
|
||||
default:
|
||||
lpfc_log_msg(phba, KERN_WARNING, LOG_INIT,
|
||||
"0548 Unknown debugfs error injection entry\n");
|
||||
break;
|
||||
}
|
||||
else if (dent == phba->debug_InjErrWWPN) {
|
||||
tmp = cpu_to_be64(tmp);
|
||||
memcpy(&phba->lpfc_injerr_wwpn, &tmp, sizeof(struct lpfc_name));
|
||||
} else
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"0548 Unknown debugfs error injection entry\n");
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
@ -5752,7 +5728,7 @@ static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
|
||||
};
|
||||
|
||||
static struct dentry *lpfc_debugfs_root = NULL;
|
||||
static unsigned int lpfc_debugfs_hba_count;
|
||||
static atomic_t lpfc_debugfs_hba_count;
|
||||
|
||||
/*
|
||||
* File operations for the iDiag debugfs
|
||||
@ -6074,12 +6050,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
|
||||
/* Setup lpfc root directory */
|
||||
if (!lpfc_debugfs_root) {
|
||||
lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
|
||||
lpfc_debugfs_hba_count = 0;
|
||||
if (IS_ERR(lpfc_debugfs_root)) {
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_INIT,
|
||||
"0527 Cannot create debugfs lpfc\n");
|
||||
return;
|
||||
}
|
||||
atomic_set(&lpfc_debugfs_hba_count, 0);
|
||||
}
|
||||
if (!lpfc_debugfs_start_time)
|
||||
lpfc_debugfs_start_time = jiffies;
|
||||
@ -6090,96 +6061,159 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
|
||||
pport_setup = true;
|
||||
phba->hba_debugfs_root =
|
||||
debugfs_create_dir(name, lpfc_debugfs_root);
|
||||
phba->debugfs_vport_count = 0;
|
||||
if (IS_ERR(phba->hba_debugfs_root)) {
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_INIT,
|
||||
"0528 Cannot create debugfs %s\n", name);
|
||||
return;
|
||||
}
|
||||
lpfc_debugfs_hba_count++;
|
||||
atomic_inc(&lpfc_debugfs_hba_count);
|
||||
atomic_set(&phba->debugfs_vport_count, 0);
|
||||
|
||||
/* Multi-XRI pools */
|
||||
debugfs_create_file("multixripools", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
&lpfc_debugfs_op_multixripools);
|
||||
snprintf(name, sizeof(name), "multixripools");
|
||||
phba->debug_multixri_pools =
|
||||
debugfs_create_file(name, S_IFREG | 0644,
|
||||
phba->hba_debugfs_root,
|
||||
phba,
|
||||
&lpfc_debugfs_op_multixripools);
|
||||
if (IS_ERR(phba->debug_multixri_pools)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"0527 Cannot create debugfs multixripools\n");
|
||||
goto debug_failed;
|
||||
}
|
||||
|
||||
/* Congestion Info Buffer */
|
||||
debugfs_create_file("cgn_buffer", 0644, phba->hba_debugfs_root,
|
||||
phba, &lpfc_cgn_buffer_op);
|
||||
scnprintf(name, sizeof(name), "cgn_buffer");
|
||||
phba->debug_cgn_buffer =
|
||||
debugfs_create_file(name, S_IFREG | 0644,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_cgn_buffer_op);
|
||||
if (IS_ERR(phba->debug_cgn_buffer)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"6527 Cannot create debugfs "
|
||||
"cgn_buffer\n");
|
||||
goto debug_failed;
|
||||
}
|
||||
|
||||
/* RX Monitor */
|
||||
debugfs_create_file("rx_monitor", 0644, phba->hba_debugfs_root,
|
||||
phba, &lpfc_rx_monitor_op);
|
||||
scnprintf(name, sizeof(name), "rx_monitor");
|
||||
phba->debug_rx_monitor =
|
||||
debugfs_create_file(name, S_IFREG | 0644,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_rx_monitor_op);
|
||||
if (IS_ERR(phba->debug_rx_monitor)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"6528 Cannot create debugfs "
|
||||
"rx_monitor\n");
|
||||
goto debug_failed;
|
||||
}
|
||||
|
||||
/* RAS log */
|
||||
debugfs_create_file("ras_log", 0644, phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_ras_log);
|
||||
snprintf(name, sizeof(name), "ras_log");
|
||||
phba->debug_ras_log =
|
||||
debugfs_create_file(name, 0644,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_ras_log);
|
||||
if (IS_ERR(phba->debug_ras_log)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"6148 Cannot create debugfs"
|
||||
" ras_log\n");
|
||||
goto debug_failed;
|
||||
}
|
||||
|
||||
/* Setup hbqinfo */
|
||||
debugfs_create_file("hbqinfo", 0644, phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_hbqinfo);
|
||||
snprintf(name, sizeof(name), "hbqinfo");
|
||||
phba->debug_hbqinfo =
|
||||
debugfs_create_file(name, S_IFREG | 0644,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_hbqinfo);
|
||||
|
||||
#ifdef LPFC_HDWQ_LOCK_STAT
|
||||
/* Setup lockstat */
|
||||
debugfs_create_file("lockstat", 0644, phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_lockstat);
|
||||
snprintf(name, sizeof(name), "lockstat");
|
||||
phba->debug_lockstat =
|
||||
debugfs_create_file(name, S_IFREG | 0644,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_lockstat);
|
||||
if (IS_ERR(phba->debug_lockstat)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"4610 Can't create debugfs lockstat\n");
|
||||
goto debug_failed;
|
||||
}
|
||||
#endif
|
||||
if (phba->sli_rev < LPFC_SLI_REV4) {
|
||||
/* Setup dumpHBASlim */
|
||||
debugfs_create_file("dumpHBASlim", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
&lpfc_debugfs_op_dumpHBASlim);
|
||||
}
|
||||
|
||||
/* Setup dumpHBASlim */
|
||||
if (phba->sli_rev < LPFC_SLI_REV4) {
|
||||
/* Setup dumpHostSlim */
|
||||
debugfs_create_file("dumpHostSlim", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
&lpfc_debugfs_op_dumpHostSlim);
|
||||
}
|
||||
snprintf(name, sizeof(name), "dumpHBASlim");
|
||||
phba->debug_dumpHBASlim =
|
||||
debugfs_create_file(name,
|
||||
S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dumpHBASlim);
|
||||
} else
|
||||
phba->debug_dumpHBASlim = NULL;
|
||||
|
||||
/* Setup dumpHostSlim */
|
||||
if (phba->sli_rev < LPFC_SLI_REV4) {
|
||||
snprintf(name, sizeof(name), "dumpHostSlim");
|
||||
phba->debug_dumpHostSlim =
|
||||
debugfs_create_file(name,
|
||||
S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dumpHostSlim);
|
||||
} else
|
||||
phba->debug_dumpHostSlim = NULL;
|
||||
|
||||
/* Setup DIF Error Injections */
|
||||
debugfs_create_file_aux_num("InjErrLBA", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
InjErrLBA,
|
||||
&lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "InjErrLBA");
|
||||
phba->debug_InjErrLBA =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
|
||||
|
||||
debugfs_create_file_aux_num("InjErrNPortID", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
InjErrNPortID,
|
||||
&lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "InjErrNPortID");
|
||||
phba->debug_InjErrNPortID =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
|
||||
debugfs_create_file_aux_num("InjErrWWPN", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
InjErrWWPN,
|
||||
&lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "InjErrWWPN");
|
||||
phba->debug_InjErrWWPN =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
|
||||
debugfs_create_file_aux_num("writeGuardInjErr", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
writeGuard,
|
||||
&lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "writeGuardInjErr");
|
||||
phba->debug_writeGuard =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
|
||||
debugfs_create_file_aux_num("writeAppInjErr", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
writeApp, &lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "writeAppInjErr");
|
||||
phba->debug_writeApp =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
|
||||
debugfs_create_file_aux_num("writeRefInjErr", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
writeRef, &lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "writeRefInjErr");
|
||||
phba->debug_writeRef =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
|
||||
debugfs_create_file_aux_num("readGuardInjErr", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
readGuard,
|
||||
&lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "readGuardInjErr");
|
||||
phba->debug_readGuard =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
|
||||
debugfs_create_file_aux_num("readAppInjErr", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
readApp, &lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "readAppInjErr");
|
||||
phba->debug_readApp =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
|
||||
debugfs_create_file_aux_num("readRefInjErr", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
readRef, &lpfc_debugfs_op_dif_err);
|
||||
snprintf(name, sizeof(name), "readRefInjErr");
|
||||
phba->debug_readRef =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_dif_err);
|
||||
|
||||
/* Setup slow ring trace */
|
||||
if (lpfc_debugfs_max_slow_ring_trc) {
|
||||
@ -6193,15 +6227,16 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
|
||||
i++;
|
||||
}
|
||||
lpfc_debugfs_max_slow_ring_trc = (1 << i);
|
||||
pr_info("lpfc_debugfs_max_slow_ring_trc "
|
||||
"changed to %d\n",
|
||||
lpfc_debugfs_max_slow_ring_trc);
|
||||
pr_err("lpfc_debugfs_max_disc_trc changed to "
|
||||
"%d\n", lpfc_debugfs_max_disc_trc);
|
||||
}
|
||||
}
|
||||
|
||||
debugfs_create_file("slow_ring_trace", 0644,
|
||||
phba->hba_debugfs_root, phba,
|
||||
&lpfc_debugfs_op_slow_ring_trc);
|
||||
snprintf(name, sizeof(name), "slow_ring_trace");
|
||||
phba->debug_slow_ring_trc =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_slow_ring_trc);
|
||||
if (!phba->slow_ring_trc) {
|
||||
phba->slow_ring_trc = kcalloc(
|
||||
lpfc_debugfs_max_slow_ring_trc,
|
||||
@ -6211,18 +6246,21 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"0416 Cannot create debugfs "
|
||||
"slow_ring buffer\n");
|
||||
goto out;
|
||||
goto debug_failed;
|
||||
}
|
||||
atomic_set(&phba->slow_ring_trc_cnt, 0);
|
||||
}
|
||||
|
||||
debugfs_create_file("nvmeio_trc", 0644, phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_nvmeio_trc);
|
||||
snprintf(name, sizeof(name), "nvmeio_trc");
|
||||
phba->debug_nvmeio_trc =
|
||||
debugfs_create_file(name, 0644,
|
||||
phba->hba_debugfs_root,
|
||||
phba, &lpfc_debugfs_op_nvmeio_trc);
|
||||
|
||||
atomic_set(&phba->nvmeio_trc_cnt, 0);
|
||||
if (lpfc_debugfs_max_nvmeio_trc) {
|
||||
num = lpfc_debugfs_max_nvmeio_trc - 1;
|
||||
if (num & lpfc_debugfs_max_nvmeio_trc) {
|
||||
if (num & lpfc_debugfs_max_disc_trc) {
|
||||
/* Change to be a power of 2 */
|
||||
num = lpfc_debugfs_max_nvmeio_trc;
|
||||
i = 0;
|
||||
@ -6231,9 +6269,10 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
|
||||
i++;
|
||||
}
|
||||
lpfc_debugfs_max_nvmeio_trc = (1 << i);
|
||||
pr_info("lpfc_debugfs_max_nvmeio_trc changed "
|
||||
"to %d\n",
|
||||
lpfc_debugfs_max_nvmeio_trc);
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"0575 lpfc_debugfs_max_nvmeio_trc "
|
||||
"changed to %d\n",
|
||||
lpfc_debugfs_max_nvmeio_trc);
|
||||
}
|
||||
phba->nvmeio_trc_size = lpfc_debugfs_max_nvmeio_trc;
|
||||
|
||||
@ -6250,6 +6289,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
|
||||
}
|
||||
phba->nvmeio_trc_on = 1;
|
||||
phba->nvmeio_trc_output_idx = 0;
|
||||
phba->nvmeio_trc = NULL;
|
||||
} else {
|
||||
nvmeio_off:
|
||||
phba->nvmeio_trc_size = 0;
|
||||
@ -6263,12 +6303,7 @@ nvmeio_off:
|
||||
if (!vport->vport_debugfs_root) {
|
||||
vport->vport_debugfs_root =
|
||||
debugfs_create_dir(name, phba->hba_debugfs_root);
|
||||
if (IS_ERR(vport->vport_debugfs_root)) {
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_INIT,
|
||||
"0529 Cannot create debugfs %s\n", name);
|
||||
return;
|
||||
}
|
||||
phba->debugfs_vport_count++;
|
||||
atomic_inc(&phba->debugfs_vport_count);
|
||||
}
|
||||
|
||||
if (lpfc_debugfs_max_disc_trc) {
|
||||
@ -6282,8 +6317,8 @@ nvmeio_off:
|
||||
i++;
|
||||
}
|
||||
lpfc_debugfs_max_disc_trc = (1 << i);
|
||||
pr_info("lpfc_debugfs_max_disc_trc changed to %d\n",
|
||||
lpfc_debugfs_max_disc_trc);
|
||||
pr_err("lpfc_debugfs_max_disc_trc changed to %d\n",
|
||||
lpfc_debugfs_max_disc_trc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6295,27 +6330,54 @@ nvmeio_off:
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"0418 Cannot create debugfs disc trace "
|
||||
"buffer\n");
|
||||
goto out;
|
||||
goto debug_failed;
|
||||
}
|
||||
atomic_set(&vport->disc_trc_cnt, 0);
|
||||
|
||||
debugfs_create_file("discovery_trace", 0644, vport->vport_debugfs_root,
|
||||
vport, &lpfc_debugfs_op_disc_trc);
|
||||
snprintf(name, sizeof(name), "discovery_trace");
|
||||
vport->debug_disc_trc =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
vport->vport_debugfs_root,
|
||||
vport, &lpfc_debugfs_op_disc_trc);
|
||||
snprintf(name, sizeof(name), "nodelist");
|
||||
vport->debug_nodelist =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
vport->vport_debugfs_root,
|
||||
vport, &lpfc_debugfs_op_nodelist);
|
||||
|
||||
debugfs_create_file("nodelist", 0644, vport->vport_debugfs_root, vport,
|
||||
&lpfc_debugfs_op_nodelist);
|
||||
snprintf(name, sizeof(name), "nvmestat");
|
||||
vport->debug_nvmestat =
|
||||
debugfs_create_file(name, 0644,
|
||||
vport->vport_debugfs_root,
|
||||
vport, &lpfc_debugfs_op_nvmestat);
|
||||
|
||||
debugfs_create_file("nvmestat", 0644, vport->vport_debugfs_root, vport,
|
||||
&lpfc_debugfs_op_nvmestat);
|
||||
snprintf(name, sizeof(name), "scsistat");
|
||||
vport->debug_scsistat =
|
||||
debugfs_create_file(name, 0644,
|
||||
vport->vport_debugfs_root,
|
||||
vport, &lpfc_debugfs_op_scsistat);
|
||||
if (IS_ERR(vport->debug_scsistat)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"4611 Cannot create debugfs scsistat\n");
|
||||
goto debug_failed;
|
||||
}
|
||||
|
||||
debugfs_create_file("scsistat", 0644, vport->vport_debugfs_root, vport,
|
||||
&lpfc_debugfs_op_scsistat);
|
||||
snprintf(name, sizeof(name), "ioktime");
|
||||
vport->debug_ioktime =
|
||||
debugfs_create_file(name, 0644,
|
||||
vport->vport_debugfs_root,
|
||||
vport, &lpfc_debugfs_op_ioktime);
|
||||
if (IS_ERR(vport->debug_ioktime)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
||||
"0815 Cannot create debugfs ioktime\n");
|
||||
goto debug_failed;
|
||||
}
|
||||
|
||||
debugfs_create_file("ioktime", 0644, vport->vport_debugfs_root, vport,
|
||||
&lpfc_debugfs_op_ioktime);
|
||||
|
||||
debugfs_create_file("hdwqstat", 0644, vport->vport_debugfs_root, vport,
|
||||
&lpfc_debugfs_op_hdwqstat);
|
||||
snprintf(name, sizeof(name), "hdwqstat");
|
||||
vport->debug_hdwqstat =
|
||||
debugfs_create_file(name, 0644,
|
||||
vport->vport_debugfs_root,
|
||||
vport, &lpfc_debugfs_op_hdwqstat);
|
||||
|
||||
/*
|
||||
* The following section is for additional directories/files for the
|
||||
@ -6323,58 +6385,93 @@ nvmeio_off:
|
||||
*/
|
||||
|
||||
if (!pport_setup)
|
||||
return;
|
||||
goto debug_failed;
|
||||
|
||||
/*
|
||||
* iDiag debugfs root entry points for SLI4 device only
|
||||
*/
|
||||
if (phba->sli_rev < LPFC_SLI_REV4)
|
||||
return;
|
||||
goto debug_failed;
|
||||
|
||||
snprintf(name, sizeof(name), "iDiag");
|
||||
if (!phba->idiag_root) {
|
||||
phba->idiag_root =
|
||||
debugfs_create_dir("iDiag", phba->hba_debugfs_root);
|
||||
debugfs_create_dir(name, phba->hba_debugfs_root);
|
||||
/* Initialize iDiag data structure */
|
||||
memset(&idiag, 0, sizeof(idiag));
|
||||
}
|
||||
|
||||
/* iDiag read PCI config space */
|
||||
debugfs_create_file("pciCfg", 0644, phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_pciCfg);
|
||||
idiag.offset.last_rd = 0;
|
||||
snprintf(name, sizeof(name), "pciCfg");
|
||||
if (!phba->idiag_pci_cfg) {
|
||||
phba->idiag_pci_cfg =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->idiag_root, phba, &lpfc_idiag_op_pciCfg);
|
||||
idiag.offset.last_rd = 0;
|
||||
}
|
||||
|
||||
/* iDiag PCI BAR access */
|
||||
debugfs_create_file("barAcc", 0644, phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_barAcc);
|
||||
idiag.offset.last_rd = 0;
|
||||
snprintf(name, sizeof(name), "barAcc");
|
||||
if (!phba->idiag_bar_acc) {
|
||||
phba->idiag_bar_acc =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->idiag_root, phba, &lpfc_idiag_op_barAcc);
|
||||
idiag.offset.last_rd = 0;
|
||||
}
|
||||
|
||||
/* iDiag get PCI function queue information */
|
||||
debugfs_create_file("queInfo", 0444, phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_queInfo);
|
||||
snprintf(name, sizeof(name), "queInfo");
|
||||
if (!phba->idiag_que_info) {
|
||||
phba->idiag_que_info =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO,
|
||||
phba->idiag_root, phba, &lpfc_idiag_op_queInfo);
|
||||
}
|
||||
|
||||
/* iDiag access PCI function queue */
|
||||
debugfs_create_file("queAcc", 0644, phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_queAcc);
|
||||
snprintf(name, sizeof(name), "queAcc");
|
||||
if (!phba->idiag_que_acc) {
|
||||
phba->idiag_que_acc =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->idiag_root, phba, &lpfc_idiag_op_queAcc);
|
||||
}
|
||||
|
||||
/* iDiag access PCI function doorbell registers */
|
||||
debugfs_create_file("drbAcc", 0644, phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_drbAcc);
|
||||
snprintf(name, sizeof(name), "drbAcc");
|
||||
if (!phba->idiag_drb_acc) {
|
||||
phba->idiag_drb_acc =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->idiag_root, phba, &lpfc_idiag_op_drbAcc);
|
||||
}
|
||||
|
||||
/* iDiag access PCI function control registers */
|
||||
debugfs_create_file("ctlAcc", 0644, phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_ctlAcc);
|
||||
snprintf(name, sizeof(name), "ctlAcc");
|
||||
if (!phba->idiag_ctl_acc) {
|
||||
phba->idiag_ctl_acc =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc);
|
||||
}
|
||||
|
||||
/* iDiag access mbox commands */
|
||||
debugfs_create_file("mbxAcc", 0644, phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_mbxAcc);
|
||||
snprintf(name, sizeof(name), "mbxAcc");
|
||||
if (!phba->idiag_mbx_acc) {
|
||||
phba->idiag_mbx_acc =
|
||||
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc);
|
||||
}
|
||||
|
||||
/* iDiag extents access commands */
|
||||
if (phba->sli4_hba.extents_in_use) {
|
||||
debugfs_create_file("extAcc", 0644, phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_extAcc);
|
||||
snprintf(name, sizeof(name), "extAcc");
|
||||
if (!phba->idiag_ext_acc) {
|
||||
phba->idiag_ext_acc =
|
||||
debugfs_create_file(name,
|
||||
S_IFREG|S_IRUGO|S_IWUSR,
|
||||
phba->idiag_root, phba,
|
||||
&lpfc_idiag_op_extAcc);
|
||||
}
|
||||
}
|
||||
out:
|
||||
/* alloc'ed items are kfree'd in lpfc_debugfs_terminate */
|
||||
|
||||
debug_failed:
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
@ -6399,26 +6496,145 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
|
||||
kfree(vport->disc_trc);
|
||||
vport->disc_trc = NULL;
|
||||
|
||||
debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
|
||||
vport->debug_disc_trc = NULL;
|
||||
|
||||
debugfs_remove(vport->debug_nodelist); /* nodelist */
|
||||
vport->debug_nodelist = NULL;
|
||||
|
||||
debugfs_remove(vport->debug_nvmestat); /* nvmestat */
|
||||
vport->debug_nvmestat = NULL;
|
||||
|
||||
debugfs_remove(vport->debug_scsistat); /* scsistat */
|
||||
vport->debug_scsistat = NULL;
|
||||
|
||||
debugfs_remove(vport->debug_ioktime); /* ioktime */
|
||||
vport->debug_ioktime = NULL;
|
||||
|
||||
debugfs_remove(vport->debug_hdwqstat); /* hdwqstat */
|
||||
vport->debug_hdwqstat = NULL;
|
||||
|
||||
if (vport->vport_debugfs_root) {
|
||||
debugfs_remove(vport->vport_debugfs_root); /* vportX */
|
||||
vport->vport_debugfs_root = NULL;
|
||||
phba->debugfs_vport_count--;
|
||||
atomic_dec(&phba->debugfs_vport_count);
|
||||
}
|
||||
|
||||
if (!phba->debugfs_vport_count) {
|
||||
if (atomic_read(&phba->debugfs_vport_count) == 0) {
|
||||
|
||||
debugfs_remove(phba->debug_multixri_pools); /* multixripools*/
|
||||
phba->debug_multixri_pools = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
|
||||
phba->debug_hbqinfo = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_cgn_buffer);
|
||||
phba->debug_cgn_buffer = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_rx_monitor);
|
||||
phba->debug_rx_monitor = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_ras_log);
|
||||
phba->debug_ras_log = NULL;
|
||||
|
||||
#ifdef LPFC_HDWQ_LOCK_STAT
|
||||
debugfs_remove(phba->debug_lockstat); /* lockstat */
|
||||
phba->debug_lockstat = NULL;
|
||||
#endif
|
||||
debugfs_remove(phba->debug_dumpHBASlim); /* HBASlim */
|
||||
phba->debug_dumpHBASlim = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_dumpHostSlim); /* HostSlim */
|
||||
phba->debug_dumpHostSlim = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */
|
||||
phba->debug_InjErrLBA = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_InjErrNPortID);
|
||||
phba->debug_InjErrNPortID = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_InjErrWWPN); /* InjErrWWPN */
|
||||
phba->debug_InjErrWWPN = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_writeGuard); /* writeGuard */
|
||||
phba->debug_writeGuard = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_writeApp); /* writeApp */
|
||||
phba->debug_writeApp = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_writeRef); /* writeRef */
|
||||
phba->debug_writeRef = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_readGuard); /* readGuard */
|
||||
phba->debug_readGuard = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_readApp); /* readApp */
|
||||
phba->debug_readApp = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_readRef); /* readRef */
|
||||
phba->debug_readRef = NULL;
|
||||
|
||||
kfree(phba->slow_ring_trc);
|
||||
phba->slow_ring_trc = NULL;
|
||||
|
||||
/* slow_ring_trace */
|
||||
debugfs_remove(phba->debug_slow_ring_trc);
|
||||
phba->debug_slow_ring_trc = NULL;
|
||||
|
||||
debugfs_remove(phba->debug_nvmeio_trc);
|
||||
phba->debug_nvmeio_trc = NULL;
|
||||
|
||||
kfree(phba->nvmeio_trc);
|
||||
phba->nvmeio_trc = NULL;
|
||||
|
||||
/*
|
||||
* iDiag release
|
||||
*/
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
/* iDiag extAcc */
|
||||
debugfs_remove(phba->idiag_ext_acc);
|
||||
phba->idiag_ext_acc = NULL;
|
||||
|
||||
/* iDiag mbxAcc */
|
||||
debugfs_remove(phba->idiag_mbx_acc);
|
||||
phba->idiag_mbx_acc = NULL;
|
||||
|
||||
/* iDiag ctlAcc */
|
||||
debugfs_remove(phba->idiag_ctl_acc);
|
||||
phba->idiag_ctl_acc = NULL;
|
||||
|
||||
/* iDiag drbAcc */
|
||||
debugfs_remove(phba->idiag_drb_acc);
|
||||
phba->idiag_drb_acc = NULL;
|
||||
|
||||
/* iDiag queAcc */
|
||||
debugfs_remove(phba->idiag_que_acc);
|
||||
phba->idiag_que_acc = NULL;
|
||||
|
||||
/* iDiag queInfo */
|
||||
debugfs_remove(phba->idiag_que_info);
|
||||
phba->idiag_que_info = NULL;
|
||||
|
||||
/* iDiag barAcc */
|
||||
debugfs_remove(phba->idiag_bar_acc);
|
||||
phba->idiag_bar_acc = NULL;
|
||||
|
||||
/* iDiag pciCfg */
|
||||
debugfs_remove(phba->idiag_pci_cfg);
|
||||
phba->idiag_pci_cfg = NULL;
|
||||
|
||||
/* Finally remove the iDiag debugfs root */
|
||||
debugfs_remove(phba->idiag_root);
|
||||
phba->idiag_root = NULL;
|
||||
}
|
||||
|
||||
if (phba->hba_debugfs_root) {
|
||||
debugfs_remove(phba->hba_debugfs_root); /* fnX */
|
||||
phba->hba_debugfs_root = NULL;
|
||||
lpfc_debugfs_hba_count--;
|
||||
atomic_dec(&lpfc_debugfs_hba_count);
|
||||
}
|
||||
|
||||
if (!lpfc_debugfs_hba_count) {
|
||||
if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
|
||||
debugfs_remove(lpfc_debugfs_root); /* lpfc */
|
||||
lpfc_debugfs_root = NULL;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2007-2011 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -44,9 +44,6 @@
|
||||
/* hbqinfo output buffer size */
|
||||
#define LPFC_HBQINFO_SIZE 8192
|
||||
|
||||
/* hdwqinfo output buffer size */
|
||||
#define LPFC_HDWQINFO_SIZE 8192
|
||||
|
||||
/* nvmestat output buffer size */
|
||||
#define LPFC_NVMESTAT_SIZE 8192
|
||||
#define LPFC_IOKTIME_SIZE 8192
|
||||
@ -325,17 +322,6 @@ enum {
|
||||
* discovery */
|
||||
#endif /* H_LPFC_DEBUG_FS */
|
||||
|
||||
enum {
|
||||
writeGuard = 1,
|
||||
writeApp,
|
||||
writeRef,
|
||||
readGuard,
|
||||
readApp,
|
||||
readRef,
|
||||
InjErrLBA,
|
||||
InjErrNPortID,
|
||||
InjErrWWPN,
|
||||
};
|
||||
|
||||
/*
|
||||
* Driver debug utility routines outside of debugfs. The debug utility
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2013 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -208,7 +208,6 @@ enum lpfc_nlp_flag {
|
||||
NPR list */
|
||||
NLP_RM_DFLT_RPI = 26, /* need to remove leftover dflt RPI */
|
||||
NLP_NODEV_REMOVE = 27, /* Defer removal till discovery ends */
|
||||
NLP_FLOGI_DFR_ACC = 28, /* FLOGI LS_ACC was Deferred */
|
||||
NLP_SC_REQ = 29, /* Target requires authentication */
|
||||
NLP_FIRSTBURST = 30, /* Target supports FirstBurst */
|
||||
NLP_RPI_REGISTERED = 31 /* nlp_rpi is valid */
|
||||
|
||||
@ -650,6 +650,8 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS2;
|
||||
if (sp->cls3.classValid)
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS3;
|
||||
if (sp->cls4.classValid)
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS4;
|
||||
ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
|
||||
sp->cmn.bbRcvSizeLsb;
|
||||
|
||||
@ -932,15 +934,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
/* Check to see if link went down during discovery */
|
||||
if (lpfc_els_chk_latt(vport)) {
|
||||
/* One additional decrement on node reference count to
|
||||
* trigger the release of the node. Make sure the ndlp
|
||||
* is marked NLP_DROPPED.
|
||||
* trigger the release of the node
|
||||
*/
|
||||
if (!test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag) &&
|
||||
!test_bit(NLP_DROPPED, &ndlp->nlp_flag) &&
|
||||
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
|
||||
set_bit(NLP_DROPPED, &ndlp->nlp_flag);
|
||||
if (!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD))
|
||||
lpfc_nlp_put(ndlp);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -998,10 +995,9 @@ stop_rr_fcf_flogi:
|
||||
IOERR_LOOP_OPEN_FAILURE)))
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"2858 FLOGI Status:x%x/x%x TMO"
|
||||
":x%x Data x%lx x%x x%lx x%x\n",
|
||||
":x%x Data x%lx x%x\n",
|
||||
ulp_status, ulp_word4, tmo,
|
||||
phba->hba_flag, phba->fcf.fcf_flag,
|
||||
ndlp->nlp_flag, ndlp->fc4_xpt_flags);
|
||||
phba->hba_flag, phba->fcf.fcf_flag);
|
||||
|
||||
/* Check for retry */
|
||||
if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
|
||||
@ -1019,17 +1015,14 @@ stop_rr_fcf_flogi:
|
||||
* reference to trigger node release.
|
||||
*/
|
||||
if (!test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag) &&
|
||||
!test_bit(NLP_DROPPED, &ndlp->nlp_flag) &&
|
||||
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
|
||||
set_bit(NLP_DROPPED, &ndlp->nlp_flag);
|
||||
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD))
|
||||
lpfc_nlp_put(ndlp);
|
||||
}
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
|
||||
"0150 FLOGI Status:x%x/x%x "
|
||||
"xri x%x iotag x%x TMO:x%x refcnt %d\n",
|
||||
"xri x%x TMO:x%x refcnt %d\n",
|
||||
ulp_status, ulp_word4, cmdiocb->sli4_xritag,
|
||||
cmdiocb->iotag, tmo, kref_read(&ndlp->kref));
|
||||
tmo, kref_read(&ndlp->kref));
|
||||
|
||||
/* If this is not a loop open failure, bail out */
|
||||
if (!(ulp_status == IOSTAT_LOCAL_REJECT &&
|
||||
@ -1286,19 +1279,6 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
uint32_t tmo, did;
|
||||
int rc;
|
||||
|
||||
/* It's possible for lpfc to reissue a FLOGI on an ndlp that is marked
|
||||
* NLP_DROPPED. This happens when the FLOGI completed with the XB bit
|
||||
* set causing lpfc to reference the ndlp until the XRI_ABORTED CQE is
|
||||
* issued. The time window for the XRI_ABORTED CQE can be as much as
|
||||
* 2*2*RA_TOV allowing for ndlp reuse of this type when the link is
|
||||
* cycling quickly. When true, restore the initial reference and remove
|
||||
* the NLP_DROPPED flag as lpfc is retrying.
|
||||
*/
|
||||
if (test_and_clear_bit(NLP_DROPPED, &ndlp->nlp_flag)) {
|
||||
if (!lpfc_nlp_get(ndlp))
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
|
||||
ndlp->nlp_DID, ELS_CMD_FLOGI);
|
||||
@ -1354,14 +1334,6 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
/* Can't do SLI4 class2 without support sequence coalescing */
|
||||
sp->cls2.classValid = 0;
|
||||
sp->cls2.seqDelivery = 0;
|
||||
|
||||
/* Fill out Auxiliary Parameter Data */
|
||||
if (phba->pni) {
|
||||
sp->aux.flags =
|
||||
AUX_PARM_DATA_VALID | AUX_PARM_PNI_VALID;
|
||||
sp->aux.pni = cpu_to_be64(phba->pni);
|
||||
sp->aux.npiv_cnt = cpu_to_be16(phba->max_vpi - 1);
|
||||
}
|
||||
} else {
|
||||
/* Historical, setting sequential-delivery bit for SLI3 */
|
||||
sp->cls2.seqDelivery = (sp->cls2.classValid) ? 1 : 0;
|
||||
@ -1441,12 +1413,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
phba->defer_flogi_acc.ox_id;
|
||||
}
|
||||
|
||||
/* The LS_ACC completion needs to drop the initial reference.
|
||||
* This is a special case for Pt2Pt because both FLOGIs need
|
||||
* to complete and lpfc defers the LS_ACC when the remote
|
||||
* FLOGI arrives before the driver's FLOGI.
|
||||
*/
|
||||
set_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag);
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
|
||||
" ox_id: x%x, hba_flag x%lx\n",
|
||||
phba->defer_flogi_acc.rx_id,
|
||||
phba->defer_flogi_acc.ox_id, phba->hba_flag);
|
||||
|
||||
/* Send deferred FLOGI ACC */
|
||||
lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, &defer_flogi_acc,
|
||||
@ -1462,14 +1433,6 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
phba->defer_flogi_acc.ndlp = NULL;
|
||||
}
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
|
||||
" ox_id: x%x, ndlp x%px hba_flag x%lx\n",
|
||||
phba->defer_flogi_acc.rx_id,
|
||||
phba->defer_flogi_acc.ox_id,
|
||||
phba->defer_flogi_acc.ndlp,
|
||||
phba->hba_flag);
|
||||
|
||||
vport->fc_myDID = did;
|
||||
}
|
||||
|
||||
@ -2285,8 +2248,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
|
||||
|
||||
sp->cmn.valid_vendor_ver_level = 0;
|
||||
memset(sp->un.vendorVersion, 0, sizeof(sp->un.vendorVersion));
|
||||
if (!test_bit(FC_PT2PT, &vport->fc_flag))
|
||||
sp->cmn.bbRcvSizeMsb &= 0xF;
|
||||
sp->cmn.bbRcvSizeMsb &= 0xF;
|
||||
|
||||
/* Check if the destination port supports VMID */
|
||||
ndlp->vmid_support = 0;
|
||||
@ -2405,7 +2367,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
mode = KERN_INFO;
|
||||
|
||||
/* Warn PRLI status */
|
||||
lpfc_vlog_msg(vport, mode, LOG_ELS,
|
||||
lpfc_printf_vlog(vport, mode, LOG_ELS,
|
||||
"2754 PRLI DID:%06X Status:x%x/x%x, "
|
||||
"data: x%x x%x x%lx\n",
|
||||
ndlp->nlp_DID, ulp_status,
|
||||
@ -3062,7 +3024,6 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
ndlp->nlp_DID, ulp_status,
|
||||
ulp_word4);
|
||||
|
||||
/* Call NLP_EVT_DEVICE_RM if link is down or LOGO is aborted */
|
||||
if (lpfc_error_lost_link(vport, ulp_status, ulp_word4))
|
||||
skip_recovery = 1;
|
||||
}
|
||||
@ -3301,7 +3262,7 @@ lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
|
||||
return -ENOMEM;
|
||||
}
|
||||
rc = lpfc_reg_rpi(phba, vport->vpi, fc_ndlp->nlp_DID,
|
||||
(u8 *)&ns_ndlp->fc_sparam, mbox, fc_ndlp->nlp_rpi);
|
||||
(u8 *)&vport->fc_sparam, mbox, fc_ndlp->nlp_rpi);
|
||||
if (rc) {
|
||||
rc = -EACCES;
|
||||
goto out;
|
||||
@ -3345,8 +3306,7 @@ lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
|
||||
*
|
||||
* This routine is a generic completion callback function for Discovery ELS cmd.
|
||||
* Currently used by the ELS command issuing routines for the ELS State Change
|
||||
* Request (SCR), lpfc_issue_els_scr(), Exchange Diagnostic Capabilities (EDC),
|
||||
* lpfc_issue_els_edc() and the ELS RDF, lpfc_issue_els_rdf().
|
||||
* Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf().
|
||||
* These commands will be retried once only for ELS timeout errors.
|
||||
**/
|
||||
static void
|
||||
@ -3419,21 +3379,11 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
lpfc_cmpl_els_edc(phba, cmdiocb, rspiocb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ulp_status) {
|
||||
/* ELS discovery cmd completes with error */
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS | LOG_CGN_MGMT,
|
||||
"4203 ELS cmd x%x error: x%x x%X\n", cmd,
|
||||
ulp_status, ulp_word4);
|
||||
|
||||
/* In the case where the ELS cmd completes with an error and
|
||||
* the node does not have RPI registered, the node is
|
||||
* outstanding and should put its initial reference.
|
||||
*/
|
||||
if ((cmd == ELS_CMD_SCR || cmd == ELS_CMD_RDF) &&
|
||||
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD) &&
|
||||
!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
|
||||
lpfc_nlp_put(ndlp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -3502,7 +3452,6 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
|
||||
uint8_t *pcmd;
|
||||
uint16_t cmdsize;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
bool node_created = false;
|
||||
|
||||
cmdsize = (sizeof(uint32_t) + sizeof(SCR));
|
||||
|
||||
@ -3512,21 +3461,21 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
|
||||
if (!ndlp)
|
||||
return 1;
|
||||
lpfc_enqueue_node(vport, ndlp);
|
||||
node_created = true;
|
||||
}
|
||||
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
|
||||
ndlp->nlp_DID, ELS_CMD_SCR);
|
||||
if (!elsiocb)
|
||||
goto out_node_created;
|
||||
return 1;
|
||||
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
rc = lpfc_reg_fab_ctrl_node(vport, ndlp);
|
||||
if (rc) {
|
||||
lpfc_els_free_iocb(phba, elsiocb);
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
|
||||
"0937 %s: Failed to reg fc node, rc %d\n",
|
||||
__func__, rc);
|
||||
goto out_free_iocb;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
pcmd = (uint8_t *)elsiocb->cmd_dmabuf->virt;
|
||||
@ -3545,27 +3494,23 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
|
||||
phba->fc_stat.elsXmitSCR++;
|
||||
elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
|
||||
elsiocb->ndlp = lpfc_nlp_get(ndlp);
|
||||
if (!elsiocb->ndlp)
|
||||
goto out_free_iocb;
|
||||
if (!elsiocb->ndlp) {
|
||||
lpfc_els_free_iocb(phba, elsiocb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||
"Issue SCR: did:x%x refcnt %d",
|
||||
ndlp->nlp_DID, kref_read(&ndlp->kref), 0);
|
||||
|
||||
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
|
||||
if (rc == IOCB_ERROR)
|
||||
goto out_iocb_error;
|
||||
if (rc == IOCB_ERROR) {
|
||||
lpfc_els_free_iocb(phba, elsiocb);
|
||||
lpfc_nlp_put(ndlp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_iocb_error:
|
||||
lpfc_nlp_put(ndlp);
|
||||
out_free_iocb:
|
||||
lpfc_els_free_iocb(phba, elsiocb);
|
||||
out_node_created:
|
||||
if (node_created)
|
||||
lpfc_nlp_put(ndlp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3652,8 +3597,8 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry)
|
||||
}
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||
"Issue RSCN: did:x%x refcnt %d",
|
||||
ndlp->nlp_DID, kref_read(&ndlp->kref), 0);
|
||||
"Issue RSCN: did:x%x",
|
||||
ndlp->nlp_DID, 0, 0);
|
||||
|
||||
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
|
||||
if (rc == IOCB_ERROR) {
|
||||
@ -3760,7 +3705,10 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
|
||||
lpfc_nlp_put(ndlp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This will cause the callback-function lpfc_cmpl_els_cmd to
|
||||
* trigger the release of the node.
|
||||
*/
|
||||
/* Don't release reference count as RDF is likely outstanding */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3778,12 +3726,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
|
||||
*
|
||||
* Return code
|
||||
* 0 - Successfully issued rdf command
|
||||
* < 0 - Failed to issue rdf command
|
||||
* -EACCES - RDF not required for NPIV_PORT
|
||||
* -ENODEV - No fabric controller device available
|
||||
* -ENOMEM - No available memory
|
||||
* -EIO - The mailbox failed to complete successfully.
|
||||
*
|
||||
* 1 - Failed to issue rdf command
|
||||
**/
|
||||
int
|
||||
lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
|
||||
@ -3794,30 +3737,25 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
|
||||
struct lpfc_nodelist *ndlp;
|
||||
uint16_t cmdsize;
|
||||
int rc;
|
||||
bool node_created = false;
|
||||
int err;
|
||||
|
||||
cmdsize = sizeof(*prdf);
|
||||
|
||||
/* RDF ELS is not required on an NPIV VN_Port. */
|
||||
if (vport->port_type == LPFC_NPIV_PORT)
|
||||
return -EACCES;
|
||||
|
||||
ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
|
||||
if (!ndlp) {
|
||||
ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
|
||||
if (!ndlp)
|
||||
return -ENODEV;
|
||||
lpfc_enqueue_node(vport, ndlp);
|
||||
node_created = true;
|
||||
}
|
||||
|
||||
/* RDF ELS is not required on an NPIV VN_Port. */
|
||||
if (vport->port_type == LPFC_NPIV_PORT)
|
||||
return -EACCES;
|
||||
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
|
||||
ndlp->nlp_DID, ELS_CMD_RDF);
|
||||
if (!elsiocb) {
|
||||
err = -ENOMEM;
|
||||
goto out_node_created;
|
||||
}
|
||||
if (!elsiocb)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Configure the payload for the supported FPIN events. */
|
||||
prdf = (struct lpfc_els_rdf_req *)elsiocb->cmd_dmabuf->virt;
|
||||
@ -3843,8 +3781,8 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
|
||||
elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
|
||||
elsiocb->ndlp = lpfc_nlp_get(ndlp);
|
||||
if (!elsiocb->ndlp) {
|
||||
err = -EIO;
|
||||
goto out_free_iocb;
|
||||
lpfc_els_free_iocb(phba, elsiocb);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||
@ -3853,19 +3791,11 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
|
||||
|
||||
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
|
||||
if (rc == IOCB_ERROR) {
|
||||
err = -EIO;
|
||||
goto out_iocb_error;
|
||||
lpfc_els_free_iocb(phba, elsiocb);
|
||||
lpfc_nlp_put(ndlp);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_iocb_error:
|
||||
lpfc_nlp_put(ndlp);
|
||||
out_free_iocb:
|
||||
lpfc_els_free_iocb(phba, elsiocb);
|
||||
out_node_created:
|
||||
if (node_created)
|
||||
lpfc_nlp_put(ndlp);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3886,23 +3816,19 @@ static int
|
||||
lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL);
|
||||
/* Send LS_ACC */
|
||||
if (rc) {
|
||||
if (lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
|
||||
"1623 Failed to RDF_ACC from x%x for x%x Data: %d\n",
|
||||
ndlp->nlp_DID, vport->fc_myDID, rc);
|
||||
"1623 Failed to RDF_ACC from x%x for x%x\n",
|
||||
ndlp->nlp_DID, vport->fc_myDID);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = lpfc_issue_els_rdf(vport, 0);
|
||||
/* Issue new RDF for reregistering */
|
||||
if (rc) {
|
||||
if (lpfc_issue_els_rdf(vport, 0)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
|
||||
"2623 Failed to re register RDF for x%x Data: %d\n",
|
||||
vport->fc_myDID, rc);
|
||||
"2623 Failed to re register RDF for x%x\n",
|
||||
vport->fc_myDID);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -4373,7 +4299,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
|
||||
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
|
||||
if (rc == IOCB_ERROR) {
|
||||
/* The additional lpfc_nlp_put will cause the following
|
||||
* lpfc_els_free_iocb routine to trigger the release of
|
||||
* lpfc_els_free_iocb routine to trigger the rlease of
|
||||
* the node.
|
||||
*/
|
||||
lpfc_els_free_iocb(phba, elsiocb);
|
||||
@ -5201,7 +5127,7 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
|
||||
{
|
||||
struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
|
||||
|
||||
/* The I/O iocb is complete. Clear the node and first dmabuf */
|
||||
/* The I/O iocb is complete. Clear the node and first dmbuf */
|
||||
elsiocb->ndlp = NULL;
|
||||
|
||||
/* cmd_dmabuf = cmd, cmd_dmabuf->next = rsp, bpl_dmabuf = bpl */
|
||||
@ -5234,12 +5160,14 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
|
||||
} else {
|
||||
buf_ptr1 = elsiocb->cmd_dmabuf;
|
||||
lpfc_els_free_data(phba, buf_ptr1);
|
||||
elsiocb->cmd_dmabuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (elsiocb->bpl_dmabuf) {
|
||||
buf_ptr = elsiocb->bpl_dmabuf;
|
||||
lpfc_els_free_bpl(phba, buf_ptr);
|
||||
elsiocb->bpl_dmabuf = NULL;
|
||||
}
|
||||
lpfc_sli_release_iocbq(phba, elsiocb);
|
||||
return 0;
|
||||
@ -5377,12 +5305,11 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
IOCB_t *irsp;
|
||||
LPFC_MBOXQ_t *mbox = NULL;
|
||||
u32 ulp_status, ulp_word4, tmo, did, iotag;
|
||||
u32 cmd;
|
||||
|
||||
if (!vport) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
|
||||
"3177 null vport in ELS rsp\n");
|
||||
goto release;
|
||||
goto out;
|
||||
}
|
||||
if (cmdiocb->context_un.mbox)
|
||||
mbox = cmdiocb->context_un.mbox;
|
||||
@ -5412,12 +5339,12 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
ulp_status, ulp_word4, did);
|
||||
/* ELS response tag <ulpIoTag> completes */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"0110 ELS response tag x%x completes fc_flag x%lx"
|
||||
"0110 ELS response tag x%x completes "
|
||||
"Data: x%x x%x x%x x%x x%lx x%x x%x x%x %p %p\n",
|
||||
iotag, vport->fc_flag, ulp_status, ulp_word4, tmo,
|
||||
iotag, ulp_status, ulp_word4, tmo,
|
||||
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
|
||||
ndlp->nlp_rpi, kref_read(&ndlp->kref), mbox, ndlp);
|
||||
if (mbox && !test_bit(FC_PT2PT, &vport->fc_flag)) {
|
||||
if (mbox) {
|
||||
if (ulp_status == 0 &&
|
||||
test_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag)) {
|
||||
if (!lpfc_unreg_rpi(vport, ndlp) &&
|
||||
@ -5476,10 +5403,6 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
}
|
||||
out_free_mbox:
|
||||
lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
|
||||
} else if (mbox && test_bit(FC_PT2PT, &vport->fc_flag) &&
|
||||
test_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag)) {
|
||||
lpfc_mbx_cmpl_reg_login(phba, mbox);
|
||||
clear_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag);
|
||||
}
|
||||
out:
|
||||
if (ndlp && shost) {
|
||||
@ -5492,7 +5415,7 @@ out:
|
||||
* these conditions because it doesn't need the login.
|
||||
*/
|
||||
if (phba->sli_rev == LPFC_SLI_REV4 &&
|
||||
vport->port_type == LPFC_NPIV_PORT &&
|
||||
vport && vport->port_type == LPFC_NPIV_PORT &&
|
||||
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
|
||||
if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE &&
|
||||
ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE &&
|
||||
@ -5508,27 +5431,6 @@ out:
|
||||
}
|
||||
}
|
||||
|
||||
/* The driver's unsolicited deferred FLOGI ACC in Pt2Pt needs to
|
||||
* release the initial reference because the put after the free_iocb
|
||||
* call removes only the reference from the defer logic. This FLOGI
|
||||
* is never registered with the SCSI transport.
|
||||
*/
|
||||
if (test_bit(FC_PT2PT, &vport->fc_flag) &&
|
||||
test_and_clear_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO,
|
||||
LOG_ELS | LOG_NODE | LOG_DISCOVERY,
|
||||
"3357 Pt2Pt Defer FLOGI ACC ndlp x%px, "
|
||||
"nflags x%lx, fc_flag x%lx\n",
|
||||
ndlp, ndlp->nlp_flag,
|
||||
vport->fc_flag);
|
||||
cmd = *((u32 *)cmdiocb->cmd_dmabuf->virt);
|
||||
if (cmd == ELS_CMD_ACC) {
|
||||
if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
|
||||
lpfc_nlp_put(ndlp);
|
||||
}
|
||||
}
|
||||
|
||||
release:
|
||||
/* Release the originating I/O reference. */
|
||||
lpfc_els_free_iocb(phba, cmdiocb);
|
||||
lpfc_nlp_put(ndlp);
|
||||
@ -5663,6 +5565,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
||||
sp->cls1.classValid = 0;
|
||||
sp->cls2.classValid = 0;
|
||||
sp->cls3.classValid = 0;
|
||||
sp->cls4.classValid = 0;
|
||||
|
||||
/* Copy our worldwide names */
|
||||
memcpy(&sp->portName, &vport->fc_sparam.portName,
|
||||
@ -5676,8 +5579,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
||||
sp->cmn.valid_vendor_ver_level = 0;
|
||||
memset(sp->un.vendorVersion, 0,
|
||||
sizeof(sp->un.vendorVersion));
|
||||
if (!test_bit(FC_PT2PT, &vport->fc_flag))
|
||||
sp->cmn.bbRcvSizeMsb &= 0xF;
|
||||
sp->cmn.bbRcvSizeMsb &= 0xF;
|
||||
|
||||
/* If our firmware supports this feature, convey that
|
||||
* info to the target using the vendor specific field.
|
||||
@ -7959,13 +7861,6 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
|
||||
|
||||
/* Move all affected nodes by pending RSCNs to NPR state. */
|
||||
list_for_each_entry_safe(ndlp, n, &vport->fc_nodes, nlp_listp) {
|
||||
if (test_bit(FC_UNLOADING, &vport->load_flag)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"1000 %s Unloading set\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ndlp->nlp_state == NLP_STE_UNUSED_NODE) ||
|
||||
!lpfc_rscn_payload_check(vport, ndlp->nlp_DID))
|
||||
continue;
|
||||
@ -8475,9 +8370,9 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
clear_bit(FC_PUBLIC_LOOP, &vport->fc_flag);
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"3311 Rcv Flogi PS x%x new PS x%x "
|
||||
"fc_flag x%lx new fc_flag x%lx, hba_flag x%lx\n",
|
||||
"fc_flag x%lx new fc_flag x%lx\n",
|
||||
port_state, vport->port_state,
|
||||
fc_flag, vport->fc_flag, phba->hba_flag);
|
||||
fc_flag, vport->fc_flag);
|
||||
|
||||
/*
|
||||
* We temporarily set fc_myDID to make it look like we are
|
||||
@ -8497,6 +8392,13 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
&wqe->xmit_els_rsp.wqe_com);
|
||||
|
||||
vport->fc_myDID = did;
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"3344 Deferring FLOGI ACC: rx_id: x%x,"
|
||||
" ox_id: x%x, hba_flag x%lx\n",
|
||||
phba->defer_flogi_acc.rx_id,
|
||||
phba->defer_flogi_acc.ox_id, phba->hba_flag);
|
||||
|
||||
phba->defer_flogi_acc.flag = true;
|
||||
|
||||
/* This nlp_get is paired with nlp_puts that reset the
|
||||
@ -8505,14 +8407,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
* processed or cancelled.
|
||||
*/
|
||||
phba->defer_flogi_acc.ndlp = lpfc_nlp_get(ndlp);
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"3344 Deferring FLOGI ACC: rx_id: x%x,"
|
||||
" ox_id: x%x, ndlp x%px, hba_flag x%lx\n",
|
||||
phba->defer_flogi_acc.rx_id,
|
||||
phba->defer_flogi_acc.ox_id,
|
||||
phba->defer_flogi_acc.ndlp,
|
||||
phba->hba_flag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -8830,7 +8724,7 @@ reject_out:
|
||||
* @cmdiocb: pointer to lpfc command iocb data structure.
|
||||
* @ndlp: pointer to a node-list data structure.
|
||||
*
|
||||
* This routine processes Read Timeout Value (RTV) IOCB received as an
|
||||
* This routine processes Read Timout Value (RTV) IOCB received as an
|
||||
* ELS unsolicited event. It first checks the remote port state. If the
|
||||
* remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
|
||||
* state, it invokes the lpfc_els_rsl_reject() routine to send the reject
|
||||
@ -10453,8 +10347,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
* Do not process any unsolicited ELS commands
|
||||
* if the ndlp is in DEV_LOSS
|
||||
*/
|
||||
if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag))
|
||||
if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag)) {
|
||||
if (newnode)
|
||||
lpfc_nlp_put(ndlp);
|
||||
goto dropit;
|
||||
}
|
||||
|
||||
elsiocb->ndlp = lpfc_nlp_get(ndlp);
|
||||
if (!elsiocb->ndlp)
|
||||
@ -10936,7 +10833,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
|
||||
/*
|
||||
* The different unsolicited event handlers would tell us
|
||||
* if they are done with "mp" by setting cmd_dmabuf/bpl_dmabuf to NULL.
|
||||
* if they are done with "mp" by setting cmd_dmabuf to NULL.
|
||||
*/
|
||||
if (elsiocb->cmd_dmabuf) {
|
||||
lpfc_in_buf_free(phba, elsiocb->cmd_dmabuf);
|
||||
@ -11356,11 +11253,6 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"0126 FDISC cmpl status: x%x/x%x)\n",
|
||||
ulp_status, ulp_word4);
|
||||
|
||||
/* drop initial reference */
|
||||
if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
|
||||
lpfc_nlp_put(ndlp);
|
||||
|
||||
goto fdisc_failed;
|
||||
}
|
||||
|
||||
@ -11516,13 +11408,6 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
sp->cls2.seqDelivery = 1;
|
||||
sp->cls3.seqDelivery = 1;
|
||||
|
||||
/* Fill out Auxiliary Parameter Data */
|
||||
if (phba->pni) {
|
||||
sp->aux.flags =
|
||||
AUX_PARM_DATA_VALID | AUX_PARM_PNI_VALID;
|
||||
sp->aux.pni = cpu_to_be64(phba->pni);
|
||||
}
|
||||
|
||||
pcmd += sizeof(uint32_t); /* CSP Word 2 */
|
||||
pcmd += sizeof(uint32_t); /* CSP Word 3 */
|
||||
pcmd += sizeof(uint32_t); /* CSP Word 4 */
|
||||
@ -12117,11 +12002,7 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
|
||||
sglq_entry->state = SGL_FREED;
|
||||
spin_unlock_irqrestore(&phba->sli4_hba.sgl_list_lock,
|
||||
iflag);
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI |
|
||||
LOG_DISCOVERY | LOG_NODE,
|
||||
"0732 ELS XRI ABORT on Node: ndlp=x%px "
|
||||
"xri=x%x\n",
|
||||
ndlp, xri);
|
||||
|
||||
if (ndlp) {
|
||||
lpfc_set_rrq_active(phba, ndlp,
|
||||
sglq_entry->sli4_lxritag,
|
||||
|
||||
@ -183,8 +183,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
||||
|
||||
/* Don't schedule a worker thread event if the vport is going down. */
|
||||
if (test_bit(FC_UNLOADING, &vport->load_flag) ||
|
||||
(phba->sli_rev == LPFC_SLI_REV4 &&
|
||||
!test_bit(HBA_SETUP, &phba->hba_flag))) {
|
||||
!test_bit(HBA_SETUP, &phba->hba_flag)) {
|
||||
|
||||
spin_lock_irqsave(&ndlp->lock, iflags);
|
||||
ndlp->rport = NULL;
|
||||
@ -424,7 +423,6 @@ lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
|
||||
struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
if (test_and_clear_bit(NLP_IN_RECOV_POST_DEV_LOSS, &ndlp->save_flags)) {
|
||||
clear_bit(NLP_DROPPED, &ndlp->nlp_flag);
|
||||
lpfc_nlp_get(ndlp);
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_NODE,
|
||||
"8438 Devloss timeout reversed on DID x%x "
|
||||
@ -567,8 +565,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
|
||||
return fcf_inuse;
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
|
||||
lpfc_nlp_put(ndlp);
|
||||
lpfc_nlp_put(ndlp);
|
||||
return fcf_inuse;
|
||||
}
|
||||
|
||||
@ -1269,10 +1266,6 @@ lpfc_linkdown(struct lpfc_hba *phba)
|
||||
}
|
||||
phba->defer_flogi_acc.flag = false;
|
||||
|
||||
/* reinitialize initial HBA flag */
|
||||
clear_bit(HBA_FLOGI_ISSUED, &phba->hba_flag);
|
||||
clear_bit(HBA_RHBA_CMPL, &phba->hba_flag);
|
||||
|
||||
/* Clear external loopback plug detected flag */
|
||||
phba->link_flag &= ~LS_EXTERNAL_LOOPBACK;
|
||||
|
||||
@ -1443,6 +1436,10 @@ lpfc_linkup(struct lpfc_hba *phba)
|
||||
phba->pport->rcv_flogi_cnt = 0;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
/* reinitialize initial HBA flag */
|
||||
clear_bit(HBA_FLOGI_ISSUED, &phba->hba_flag);
|
||||
clear_bit(HBA_RHBA_CMPL, &phba->hba_flag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4373,8 +4370,6 @@ out:
|
||||
lpfc_ns_cmd(vport, SLI_CTNS_RNN_ID, 0, 0);
|
||||
lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
|
||||
lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
|
||||
if (phba->pni)
|
||||
lpfc_ns_cmd(vport, SLI_CTNS_RSPNI_PNI, 0, 0);
|
||||
lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0);
|
||||
|
||||
if ((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
|
||||
@ -6600,11 +6595,6 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp)
|
||||
unsigned long flags;
|
||||
|
||||
if (ndlp) {
|
||||
lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
|
||||
"node get: did:x%x flg:x%lx refcnt:x%x",
|
||||
ndlp->nlp_DID, ndlp->nlp_flag,
|
||||
kref_read(&ndlp->kref));
|
||||
|
||||
/* The check of ndlp usage to prevent incrementing the
|
||||
* ndlp reference count that is in the process of being
|
||||
* released.
|
||||
@ -6612,9 +6602,8 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp)
|
||||
spin_lock_irqsave(&ndlp->lock, flags);
|
||||
if (!kref_get_unless_zero(&ndlp->kref)) {
|
||||
spin_unlock_irqrestore(&ndlp->lock, flags);
|
||||
lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE,
|
||||
"0276 %s: ndlp:x%px refcnt:%d\n",
|
||||
__func__, (void *)ndlp, kref_read(&ndlp->kref));
|
||||
pr_info("0276 %s: NDLP has zero reference count. "
|
||||
"Exiting\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&ndlp->lock, flags);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -168,11 +168,6 @@ struct lpfc_sli_ct_request {
|
||||
uint8_t len;
|
||||
uint8_t symbname[255];
|
||||
} rspn;
|
||||
struct rspni { /* For RSPNI_PNI requests */
|
||||
__be64 pni;
|
||||
u8 len;
|
||||
u8 symbname[255];
|
||||
} rspni;
|
||||
struct gff {
|
||||
uint32_t PortId;
|
||||
} gff;
|
||||
@ -218,8 +213,6 @@ struct lpfc_sli_ct_request {
|
||||
sizeof(struct da_id))
|
||||
#define RSPN_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
|
||||
sizeof(struct rspn))
|
||||
#define RSPNI_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
|
||||
sizeof(struct rspni))
|
||||
|
||||
/*
|
||||
* FsType Definitions
|
||||
@ -316,7 +309,6 @@ struct lpfc_sli_ct_request {
|
||||
#define SLI_CTNS_RIP_NN 0x0235
|
||||
#define SLI_CTNS_RIPA_NN 0x0236
|
||||
#define SLI_CTNS_RSNN_NN 0x0239
|
||||
#define SLI_CTNS_RSPNI_PNI 0x0240
|
||||
#define SLI_CTNS_DA_ID 0x0300
|
||||
|
||||
/*
|
||||
@ -374,7 +366,6 @@ struct lpfc_name {
|
||||
} s;
|
||||
uint8_t wwn[8];
|
||||
uint64_t name __packed __aligned(4);
|
||||
__be64 wwn_be __packed __aligned(4);
|
||||
} u;
|
||||
};
|
||||
|
||||
@ -520,21 +511,6 @@ struct class_parms {
|
||||
uint8_t word3Reserved2; /* Fc Word 3, bit 0: 7 */
|
||||
};
|
||||
|
||||
enum aux_parm_flags {
|
||||
AUX_PARM_PNI_VALID = 0x20, /* FC Word 0, bit 29 */
|
||||
AUX_PARM_DATA_VALID = 0x40, /* FC Word 0, bit 30 */
|
||||
};
|
||||
|
||||
struct aux_parm {
|
||||
u8 flags; /* FC Word 0, bit 31:24 */
|
||||
u8 ext_feat[3]; /* FC Word 0, bit 23:0 */
|
||||
|
||||
__be64 pni; /* FC Word 1 and 2, platform name identifier */
|
||||
|
||||
__be16 rsvd; /* FC Word 3, bit 31:16 */
|
||||
__be16 npiv_cnt; /* FC Word 3, bit 15:0 */
|
||||
} __packed;
|
||||
|
||||
struct serv_parm { /* Structure is in Big Endian format */
|
||||
struct csp cmn;
|
||||
struct lpfc_name portName;
|
||||
@ -542,7 +518,7 @@ struct serv_parm { /* Structure is in Big Endian format */
|
||||
struct class_parms cls1;
|
||||
struct class_parms cls2;
|
||||
struct class_parms cls3;
|
||||
struct aux_parm aux;
|
||||
struct class_parms cls4;
|
||||
union {
|
||||
uint8_t vendorVersion[16];
|
||||
struct {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -1328,9 +1328,6 @@ struct cq_context {
|
||||
#define LPFC_CQ_CNT_512 0x1
|
||||
#define LPFC_CQ_CNT_1024 0x2
|
||||
#define LPFC_CQ_CNT_WORD7 0x3
|
||||
#define lpfc_cq_context_cqe_sz_SHIFT 25
|
||||
#define lpfc_cq_context_cqe_sz_MASK 0x00000003
|
||||
#define lpfc_cq_context_cqe_sz_WORD word0
|
||||
#define lpfc_cq_context_autovalid_SHIFT 15
|
||||
#define lpfc_cq_context_autovalid_MASK 0x00000001
|
||||
#define lpfc_cq_context_autovalid_WORD word0
|
||||
@ -1386,9 +1383,9 @@ struct lpfc_mbx_cq_create_set {
|
||||
#define lpfc_mbx_cq_create_set_valid_SHIFT 29
|
||||
#define lpfc_mbx_cq_create_set_valid_MASK 0x00000001
|
||||
#define lpfc_mbx_cq_create_set_valid_WORD word1
|
||||
#define lpfc_mbx_cq_create_set_cqecnt_SHIFT 27
|
||||
#define lpfc_mbx_cq_create_set_cqecnt_MASK 0x00000003
|
||||
#define lpfc_mbx_cq_create_set_cqecnt_WORD word1
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_SHIFT 27
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_MASK 0x00000003
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_WORD word1
|
||||
#define lpfc_mbx_cq_create_set_cqe_size_SHIFT 25
|
||||
#define lpfc_mbx_cq_create_set_cqe_size_MASK 0x00000003
|
||||
#define lpfc_mbx_cq_create_set_cqe_size_WORD word1
|
||||
@ -1401,16 +1398,13 @@ struct lpfc_mbx_cq_create_set {
|
||||
#define lpfc_mbx_cq_create_set_clswm_SHIFT 12
|
||||
#define lpfc_mbx_cq_create_set_clswm_MASK 0x00000003
|
||||
#define lpfc_mbx_cq_create_set_clswm_WORD word1
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_hi_SHIFT 0
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_hi_MASK 0x0000001F
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_hi_WORD word1
|
||||
uint32_t word2;
|
||||
#define lpfc_mbx_cq_create_set_arm_SHIFT 31
|
||||
#define lpfc_mbx_cq_create_set_arm_MASK 0x00000001
|
||||
#define lpfc_mbx_cq_create_set_arm_WORD word2
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_lo_SHIFT 16
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_lo_MASK 0x00007FFF
|
||||
#define lpfc_mbx_cq_create_set_cqe_cnt_lo_WORD word2
|
||||
#define lpfc_mbx_cq_create_set_cq_cnt_SHIFT 16
|
||||
#define lpfc_mbx_cq_create_set_cq_cnt_MASK 0x00007FFF
|
||||
#define lpfc_mbx_cq_create_set_cq_cnt_WORD word2
|
||||
#define lpfc_mbx_cq_create_set_num_cq_SHIFT 0
|
||||
#define lpfc_mbx_cq_create_set_num_cq_MASK 0x0000FFFF
|
||||
#define lpfc_mbx_cq_create_set_num_cq_WORD word2
|
||||
|
||||
@ -2627,33 +2627,27 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_BMID:
|
||||
m = (typeof(m)){"LP1150", "PCI-X2",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LP1150", "PCI-X2", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_BSMB:
|
||||
m = (typeof(m)){"LP111", "PCI-X2",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZEPHYR:
|
||||
m = (typeof(m)){"LPe11000", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe11000", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZEPHYR_SCSP:
|
||||
m = (typeof(m)){"LPe11000", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe11000", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZEPHYR_DCSP:
|
||||
m = (typeof(m)){"LP2105", "PCIe",
|
||||
"Obsolete, Unsupported FCoE Adapter"};
|
||||
m = (typeof(m)){"LP2105", "PCIe", "FCoE Adapter"};
|
||||
GE = 1;
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZMID:
|
||||
m = (typeof(m)){"LPe1150", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe1150", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZSMB:
|
||||
m = (typeof(m)){"LPe111", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe111", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LP101:
|
||||
m = (typeof(m)){"LP101", "PCI-X",
|
||||
@ -2672,28 +2666,22 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT:
|
||||
m = (typeof(m)){"LPe12000", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe12000", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_MID:
|
||||
m = (typeof(m)){"LPe1250", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe1250", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_SMB:
|
||||
m = (typeof(m)){"LPe121", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe121", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_DCSP:
|
||||
m = (typeof(m)){"LPe12002-SP", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe12002-SP", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_SCSP:
|
||||
m = (typeof(m)){"LPe12000-SP", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe12000-SP", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_S:
|
||||
m = (typeof(m)){"LPe12000-S", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe12000-S", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_PROTEUS_VF:
|
||||
m = (typeof(m)){"LPev12000", "PCIe IOV",
|
||||
@ -2709,25 +2697,22 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
||||
break;
|
||||
case PCI_DEVICE_ID_TIGERSHARK:
|
||||
oneConnect = 1;
|
||||
m = (typeof(m)){"OCe10100", "PCIe",
|
||||
"Obsolete, Unsupported FCoE Adapter"};
|
||||
m = (typeof(m)){"OCe10100", "PCIe", "FCoE"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_TOMCAT:
|
||||
oneConnect = 1;
|
||||
m = (typeof(m)){"OCe11100", "PCIe",
|
||||
"Obsolete, Unsupported FCoE Adapter"};
|
||||
m = (typeof(m)){"OCe11100", "PCIe", "FCoE"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_FALCON:
|
||||
m = (typeof(m)){"LPSe12002-ML1-E", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
"EmulexSecure Fibre"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_BALIUS:
|
||||
m = (typeof(m)){"LPVe12002", "PCIe Shared I/O",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LANCER_FC:
|
||||
m = (typeof(m)){"LPe16000", "PCIe",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
m = (typeof(m)){"LPe16000", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LANCER_FC_VF:
|
||||
m = (typeof(m)){"LPe16000", "PCIe",
|
||||
@ -2735,13 +2720,12 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
||||
break;
|
||||
case PCI_DEVICE_ID_LANCER_FCOE:
|
||||
oneConnect = 1;
|
||||
m = (typeof(m)){"OCe15100", "PCIe",
|
||||
"Obsolete, Unsupported FCoE Adapter"};
|
||||
m = (typeof(m)){"OCe15100", "PCIe", "FCoE"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LANCER_FCOE_VF:
|
||||
oneConnect = 1;
|
||||
m = (typeof(m)){"OCe15100", "PCIe",
|
||||
"Obsolete, Unsupported FCoE Adapter"};
|
||||
"Obsolete, Unsupported FCoE"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LANCER_G6_FC:
|
||||
m = (typeof(m)){"LPe32000", "PCIe", "Fibre Channel Adapter"};
|
||||
@ -2755,8 +2739,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
||||
case PCI_DEVICE_ID_SKYHAWK:
|
||||
case PCI_DEVICE_ID_SKYHAWK_VF:
|
||||
oneConnect = 1;
|
||||
m = (typeof(m)){"OCe14000", "PCIe",
|
||||
"Obsolete, Unsupported FCoE Adapter"};
|
||||
m = (typeof(m)){"OCe14000", "PCIe", "FCoE"};
|
||||
break;
|
||||
default:
|
||||
m = (typeof(m)){"Unknown", "", ""};
|
||||
@ -3057,6 +3040,19 @@ lpfc_cleanup(struct lpfc_vport *vport)
|
||||
lpfc_vmid_vport_cleanup(vport);
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
if (vport->port_type != LPFC_PHYSICAL_PORT &&
|
||||
ndlp->nlp_DID == Fabric_DID) {
|
||||
/* Just free up ndlp with Fabric_DID for vports */
|
||||
lpfc_nlp_put(ndlp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ndlp->nlp_DID == Fabric_Cntl_DID &&
|
||||
ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
|
||||
lpfc_nlp_put(ndlp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fabric Ports not in UNMAPPED state are cleaned up in the
|
||||
* DEVICE_RM event.
|
||||
*/
|
||||
@ -7923,6 +7919,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
int longs;
|
||||
int extra;
|
||||
uint64_t wwn;
|
||||
u32 if_type;
|
||||
u32 if_fam;
|
||||
|
||||
phba->sli4_hba.num_present_cpu = lpfc_present_cpu;
|
||||
phba->sli4_hba.num_possible_cpu = cpumask_last(cpu_possible_mask) + 1;
|
||||
@ -8182,11 +8180,28 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
*/
|
||||
rc = lpfc_get_sli4_parameters(phba, mboxq);
|
||||
if (rc) {
|
||||
lpfc_log_msg(phba, KERN_WARNING, LOG_INIT,
|
||||
"2999 Could not get SLI4 parameters\n");
|
||||
rc = -EIO;
|
||||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
goto out_free_bsmbx;
|
||||
if_type = bf_get(lpfc_sli_intf_if_type,
|
||||
&phba->sli4_hba.sli_intf);
|
||||
if_fam = bf_get(lpfc_sli_intf_sli_family,
|
||||
&phba->sli4_hba.sli_intf);
|
||||
if (phba->sli4_hba.extents_in_use &&
|
||||
phba->sli4_hba.rpi_hdrs_in_use) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2999 Unsupported SLI4 Parameters "
|
||||
"Extents and RPI headers enabled.\n");
|
||||
if (if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
|
||||
if_fam == LPFC_SLI_INTF_FAMILY_BE2) {
|
||||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
rc = -EIO;
|
||||
goto out_free_bsmbx;
|
||||
}
|
||||
}
|
||||
if (!(if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
|
||||
if_fam == LPFC_SLI_INTF_FAMILY_BE2)) {
|
||||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
rc = -EIO;
|
||||
goto out_free_bsmbx;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -8287,7 +8302,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
phba->cfg_total_seg_cnt, phba->cfg_scsi_seg_cnt,
|
||||
phba->cfg_nvme_seg_cnt);
|
||||
|
||||
i = min(phba->cfg_sg_dma_buf_size, SLI4_PAGE_SIZE);
|
||||
if (phba->cfg_sg_dma_buf_size < SLI4_PAGE_SIZE)
|
||||
i = phba->cfg_sg_dma_buf_size;
|
||||
else
|
||||
i = SLI4_PAGE_SIZE;
|
||||
|
||||
phba->lpfc_sg_dma_buf_pool =
|
||||
dma_pool_create("lpfc_sg_dma_buf_pool",
|
||||
@ -9076,9 +9094,9 @@ lpfc_setup_fdmi_mask(struct lpfc_vport *vport)
|
||||
vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
|
||||
}
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
|
||||
"6077 Setup FDMI mask: hba x%x port x%x\n",
|
||||
vport->fdmi_hba_mask, vport->fdmi_port_mask);
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
|
||||
"6077 Setup FDMI mask: hba x%x port x%x\n",
|
||||
vport->fdmi_hba_mask, vport->fdmi_port_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -326,14 +326,8 @@ lpfc_defer_plogi_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *login_mbox)
|
||||
/* Now that REG_RPI completed successfully,
|
||||
* we can now proceed with sending the PLOGI ACC.
|
||||
*/
|
||||
if (test_bit(FC_PT2PT, &ndlp->vport->fc_flag)) {
|
||||
rc = lpfc_els_rsp_acc(login_mbox->vport, ELS_CMD_PLOGI,
|
||||
save_iocb, ndlp, login_mbox);
|
||||
} else {
|
||||
rc = lpfc_els_rsp_acc(login_mbox->vport, ELS_CMD_PLOGI,
|
||||
save_iocb, ndlp, NULL);
|
||||
}
|
||||
|
||||
rc = lpfc_els_rsp_acc(login_mbox->vport, ELS_CMD_PLOGI,
|
||||
save_iocb, ndlp, NULL);
|
||||
if (rc) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"4576 PLOGI ACC fails pt2pt discovery: "
|
||||
@ -341,16 +335,9 @@ lpfc_defer_plogi_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *login_mbox)
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a fabric topology, complete the reg_rpi and prli now.
|
||||
* For Pt2Pt, the reg_rpi and PRLI are deferred until after the LS_ACC
|
||||
* completes. This ensures, in Pt2Pt, that the PLOGI LS_ACC is sent
|
||||
* before the PRLI.
|
||||
*/
|
||||
if (!test_bit(FC_PT2PT, &ndlp->vport->fc_flag)) {
|
||||
/* Now process the REG_RPI cmpl */
|
||||
lpfc_mbx_cmpl_reg_login(phba, login_mbox);
|
||||
clear_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag);
|
||||
}
|
||||
/* Now process the REG_RPI cmpl */
|
||||
lpfc_mbx_cmpl_reg_login(phba, login_mbox);
|
||||
clear_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag);
|
||||
kfree(save_iocb);
|
||||
}
|
||||
|
||||
@ -432,6 +419,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS2;
|
||||
if (sp->cls3.classValid)
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS3;
|
||||
if (sp->cls4.classValid)
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS4;
|
||||
ndlp->nlp_maxframe =
|
||||
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
|
||||
/* if already logged in, do implicit logout */
|
||||
@ -450,7 +439,18 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
*/
|
||||
if (!(ndlp->nlp_type & NLP_FABRIC) &&
|
||||
!(phba->nvmet_support)) {
|
||||
break;
|
||||
/* Clear ndlp info, since follow up PRLI may have
|
||||
* updated ndlp information
|
||||
*/
|
||||
ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
|
||||
ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR);
|
||||
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
|
||||
ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;
|
||||
clear_bit(NLP_FIRSTBURST, &ndlp->nlp_flag);
|
||||
|
||||
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,
|
||||
ndlp, NULL);
|
||||
return 1;
|
||||
}
|
||||
if (nlp_portwwn != 0 &&
|
||||
nlp_portwwn != wwn_to_u64(sp->portName.u.wwn))
|
||||
@ -472,9 +472,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
|
||||
break;
|
||||
}
|
||||
/* Clear ndlp info, since follow up processes may have
|
||||
* updated ndlp information
|
||||
*/
|
||||
|
||||
ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
|
||||
ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR);
|
||||
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
|
||||
@ -1415,6 +1413,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS2;
|
||||
if (sp->cls3.classValid)
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS3;
|
||||
if (sp->cls4.classValid)
|
||||
ndlp->nlp_class_sup |= FC_COS_CLASS4;
|
||||
ndlp->nlp_maxframe =
|
||||
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
|
||||
|
||||
|
||||
@ -1234,8 +1234,12 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
|
||||
if ((phba->cfg_nvme_enable_fb) &&
|
||||
test_bit(NLP_FIRSTBURST, &pnode->nlp_flag)) {
|
||||
req_len = lpfc_ncmd->nvmeCmd->payload_length;
|
||||
wqe->fcp_iwrite.initial_xfer_len = min(req_len,
|
||||
pnode->nvme_fb_size);
|
||||
if (req_len < pnode->nvme_fb_size)
|
||||
wqe->fcp_iwrite.initial_xfer_len =
|
||||
req_len;
|
||||
else
|
||||
wqe->fcp_iwrite.initial_xfer_len =
|
||||
pnode->nvme_fb_size;
|
||||
} else {
|
||||
wqe->fcp_iwrite.initial_xfer_len = 0;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -390,10 +390,6 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
|
||||
if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
|
||||
return;
|
||||
|
||||
/* may be called before queues established if hba_setup fails */
|
||||
if (!phba->sli4_hba.hdwq)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||
for (idx = 0; idx < phba->cfg_hdw_queue; idx++) {
|
||||
qp = &phba->sli4_hba.hdwq[idx];
|
||||
@ -536,8 +532,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
|
||||
psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
|
||||
psb->flags &= ~LPFC_SBUF_XBUSY;
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
||||
if (test_bit(HBA_SETUP, &phba->hba_flag) &&
|
||||
!list_empty(&pring->txq))
|
||||
if (!list_empty(&pring->txq))
|
||||
lpfc_worker_wake_up(phba);
|
||||
return;
|
||||
}
|
||||
@ -5936,7 +5931,7 @@ lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct fc_rport *rport)
|
||||
/**
|
||||
* lpfc_reset_flush_io_context -
|
||||
* @vport: The virtual port (scsi_host) for the flush context
|
||||
* @tgt_id: If aborting by Target context - specifies the target id
|
||||
* @tgt_id: If aborting by Target contect - specifies the target id
|
||||
* @lun_id: If aborting by Lun context - specifies the lun id
|
||||
* @context: specifies the context level to flush at.
|
||||
*
|
||||
@ -6110,14 +6105,8 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
|
||||
pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
|
||||
spin_unlock_irqrestore(&pnode->lock, flags);
|
||||
}
|
||||
status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
|
||||
LPFC_CTX_TGT);
|
||||
if (status != SUCCESS) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
|
||||
"0726 Target Reset flush status x%x\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
|
||||
LPFC_CTX_TGT);
|
||||
return FAST_IO_FAIL;
|
||||
}
|
||||
|
||||
@ -6210,7 +6199,7 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd)
|
||||
int rc, ret = SUCCESS;
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
|
||||
"3172 SCSI layer issued Host Reset\n");
|
||||
"3172 SCSI layer issued Host Reset Data:\n");
|
||||
|
||||
lpfc_offline_prep(phba, LPFC_MBX_WAIT);
|
||||
lpfc_offline(phba);
|
||||
|
||||
@ -27,8 +27,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
@ -5162,6 +5160,7 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
|
||||
phba->link_events = 0;
|
||||
phba->pport->fc_myDID = 0;
|
||||
phba->pport->fc_prevDID = 0;
|
||||
clear_bit(HBA_SETUP, &phba->hba_flag);
|
||||
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
psli->sli_flag &= ~(LPFC_PROCESS_LA);
|
||||
@ -5278,7 +5277,6 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
|
||||
"0296 Restart HBA Data: x%x x%x\n",
|
||||
phba->pport->port_state, psli->sli_flag);
|
||||
|
||||
clear_bit(HBA_SETUP, &phba->hba_flag);
|
||||
lpfc_sli4_queue_unset(phba);
|
||||
|
||||
rc = lpfc_sli4_brdreset(phba);
|
||||
@ -8441,70 +8439,6 @@ lpfc_set_host_tm(struct lpfc_hba *phba)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_get_platform_uuid - Attempts to extract a platform uuid
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
*
|
||||
* This routine attempts to first read SMBIOS DMI data for the System
|
||||
* Information structure offset 08h called System UUID. Else, no platform
|
||||
* UUID will be advertised.
|
||||
**/
|
||||
static void
|
||||
lpfc_get_platform_uuid(struct lpfc_hba *phba)
|
||||
{
|
||||
int rc;
|
||||
const char *uuid;
|
||||
char pni[17] = {0}; /* 16 characters + '\0' */
|
||||
bool is_ff = true, is_00 = true;
|
||||
u8 i;
|
||||
|
||||
/* First attempt SMBIOS DMI */
|
||||
uuid = dmi_get_system_info(DMI_PRODUCT_UUID);
|
||||
if (uuid) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
||||
"2088 SMBIOS UUID %s\n",
|
||||
uuid);
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
||||
"2099 Could not extract UUID\n");
|
||||
}
|
||||
|
||||
if (uuid && uuid_is_valid(uuid)) {
|
||||
/* Generate PNI from UUID format.
|
||||
*
|
||||
* 1.) Extract lower 64 bits from UUID format.
|
||||
* 2.) Set 3h for NAA Locally Assigned Name Identifier format.
|
||||
*
|
||||
* e.g. xxxxxxxx-xxxx-xxxx-yyyy-yyyyyyyyyyyy
|
||||
*
|
||||
* extract the yyyy-yyyyyyyyyyyy portion
|
||||
* final PNI 3yyyyyyyyyyyyyyy
|
||||
*/
|
||||
scnprintf(pni, sizeof(pni), "3%c%c%c%s",
|
||||
uuid[20], uuid[21], uuid[22], &uuid[24]);
|
||||
|
||||
/* Sanitize the converted PNI */
|
||||
for (i = 1; i < 16 && (is_ff || is_00); i++) {
|
||||
if (pni[i] != '0')
|
||||
is_00 = false;
|
||||
if (pni[i] != 'f' && pni[i] != 'F')
|
||||
is_ff = false;
|
||||
}
|
||||
|
||||
/* Convert from char* to unsigned long */
|
||||
rc = kstrtoul(pni, 16, &phba->pni);
|
||||
if (!rc && !is_ff && !is_00) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
||||
"2100 PNI 0x%016lx\n", phba->pni);
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
||||
"2101 PNI %s generation status %d\n",
|
||||
pni, rc);
|
||||
phba->pni = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_hba_setup - SLI4 device initialization PCI function
|
||||
* @phba: Pointer to HBA context object.
|
||||
@ -8588,10 +8522,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
|
||||
clear_bit(HBA_FCOE_MODE, &phba->hba_flag);
|
||||
}
|
||||
|
||||
/* Obtain platform UUID, only for SLI4 FC adapters */
|
||||
if (!test_bit(HBA_FCOE_MODE, &phba->hba_flag))
|
||||
lpfc_get_platform_uuid(phba);
|
||||
|
||||
if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) ==
|
||||
LPFC_DCBX_CEE_MODE)
|
||||
set_bit(HBA_FIP_SUPPORT, &phba->hba_flag);
|
||||
@ -8883,7 +8813,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
|
||||
if (unlikely(rc)) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"0381 Error %d during queue setup.\n", rc);
|
||||
goto out_destroy_queue;
|
||||
goto out_stop_timers;
|
||||
}
|
||||
/* Initialize the driver internal SLI layer lists. */
|
||||
lpfc_sli4_setup(phba);
|
||||
@ -9166,6 +9096,7 @@ out_free_iocblist:
|
||||
lpfc_free_iocb_list(phba);
|
||||
out_destroy_queue:
|
||||
lpfc_sli4_queue_destroy(phba);
|
||||
out_stop_timers:
|
||||
lpfc_stop_hba_timers(phba);
|
||||
out_free_mbox:
|
||||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
@ -12505,11 +12436,19 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
}
|
||||
|
||||
/*
|
||||
* Always abort the outstanding WQE and set the IA bit correctly
|
||||
* for the context. This is necessary for correctly removing
|
||||
* outstanding ndlp reference counts when the CQE completes with
|
||||
* the XB bit set.
|
||||
* If we're unloading, don't abort iocb on the ELS ring, but change
|
||||
* the callback so that nothing happens when it finishes.
|
||||
*/
|
||||
if (test_bit(FC_UNLOADING, &vport->load_flag) &&
|
||||
pring->ringno == LPFC_ELS_RING) {
|
||||
if (cmdiocb->cmd_flag & LPFC_IO_FABRIC)
|
||||
cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl;
|
||||
else
|
||||
cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* issue ABTS for this IOCB based on iotag */
|
||||
abtsiocbp = __lpfc_sli_get_iocbq(phba);
|
||||
if (abtsiocbp == NULL)
|
||||
return IOCB_NORESOURCE;
|
||||
@ -16537,10 +16476,10 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
|
||||
case 4096:
|
||||
if (phba->sli4_hba.pc_sli4_params.cqv ==
|
||||
LPFC_Q_CREATE_VERSION_2) {
|
||||
bf_set(lpfc_mbx_cq_create_set_cqe_cnt_lo,
|
||||
bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
|
||||
&cq_set->u.request,
|
||||
cq->entry_count);
|
||||
bf_set(lpfc_mbx_cq_create_set_cqecnt,
|
||||
cq->entry_count);
|
||||
bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
|
||||
&cq_set->u.request,
|
||||
LPFC_CQ_CNT_WORD7);
|
||||
break;
|
||||
@ -16556,15 +16495,15 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
|
||||
}
|
||||
fallthrough; /* otherwise default to smallest */
|
||||
case 256:
|
||||
bf_set(lpfc_mbx_cq_create_set_cqecnt,
|
||||
bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
|
||||
&cq_set->u.request, LPFC_CQ_CNT_256);
|
||||
break;
|
||||
case 512:
|
||||
bf_set(lpfc_mbx_cq_create_set_cqecnt,
|
||||
bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
|
||||
&cq_set->u.request, LPFC_CQ_CNT_512);
|
||||
break;
|
||||
case 1024:
|
||||
bf_set(lpfc_mbx_cq_create_set_cqecnt,
|
||||
bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
|
||||
&cq_set->u.request, LPFC_CQ_CNT_1024);
|
||||
break;
|
||||
}
|
||||
@ -19927,15 +19866,13 @@ lpfc_sli4_remove_rpis(struct lpfc_hba *phba)
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_resume_rpi - Resume traffic relative to an RPI
|
||||
* lpfc_sli4_resume_rpi - Remove the rpi bitmask region
|
||||
* @ndlp: pointer to lpfc nodelist data structure.
|
||||
* @cmpl: completion call-back.
|
||||
* @iocbq: data to load as mbox ctx_u information
|
||||
*
|
||||
* Return codes
|
||||
* 0 - successful
|
||||
* -ENOMEM - No available memory
|
||||
* -EIO - The mailbox failed to complete successfully.
|
||||
* This routine is invoked to remove the memory region that
|
||||
* provided rpi via a bitmask.
|
||||
**/
|
||||
int
|
||||
lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp,
|
||||
@ -19965,6 +19902,7 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Post all rpi memory regions to the port. */
|
||||
lpfc_resume_rpi(mboxq, ndlp);
|
||||
if (cmpl) {
|
||||
mboxq->mbox_cmpl = cmpl;
|
||||
@ -21434,7 +21372,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
|
||||
struct lpfc_sglq *sglq;
|
||||
struct lpfc_sli_ring *pring;
|
||||
unsigned long iflags;
|
||||
int ret = 0;
|
||||
uint32_t ret = 0;
|
||||
|
||||
/* NVME_LS and NVME_LS ABTS requests. */
|
||||
if (pwqe->cmd_flag & LPFC_IO_NVME_LS) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
@ -575,10 +575,8 @@ struct lpfc_pc_sli4_params {
|
||||
|
||||
#define LPFC_CQ_4K_PAGE_SZ 0x1
|
||||
#define LPFC_CQ_16K_PAGE_SZ 0x4
|
||||
#define LPFC_CQ_32K_PAGE_SZ 0x8
|
||||
#define LPFC_WQ_4K_PAGE_SZ 0x1
|
||||
#define LPFC_WQ_16K_PAGE_SZ 0x4
|
||||
#define LPFC_WQ_32K_PAGE_SZ 0x8
|
||||
|
||||
struct lpfc_iov {
|
||||
uint32_t pf_number;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user