Import of kernel-5.14.0-687.12.1.el9_8
This commit is contained in:
parent
97e9ce0749
commit
a19517f55f
@ -2,7 +2,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
# To debug, uncomment the following line
|
||||
# set -x
|
||||
|
||||
@ -187,7 +187,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
|
||||
* is unbound or probed and that userspace can't access its
|
||||
* configuration space while we perform recovery.
|
||||
*/
|
||||
pci_dev_lock(pdev);
|
||||
device_lock(&pdev->dev);
|
||||
if (pdev->error_state == pci_channel_io_perm_failure) {
|
||||
ers_res = PCI_ERS_RESULT_DISCONNECT;
|
||||
goto out_unlock;
|
||||
@ -254,7 +254,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
|
||||
if (driver->err_handler->resume)
|
||||
driver->err_handler->resume(pdev);
|
||||
out_unlock:
|
||||
pci_dev_unlock(pdev);
|
||||
device_unlock(&pdev->dev);
|
||||
zpci_report_status(zdev, "recovery", status_str);
|
||||
|
||||
return ers_res;
|
||||
|
||||
@ -122,6 +122,7 @@ vmlinux-objs-$(CONFIG_EFI_SBAT) += $(obj)/sbat.o
|
||||
ifdef CONFIG_EFI_SBAT
|
||||
# Strip quotes
|
||||
$(obj)/sbat.o: $(strip $(subst ",,$(CONFIG_EFI_SBAT_FILE)))
|
||||
AFLAGS_sbat.o += -I $(srctree)
|
||||
endif
|
||||
|
||||
$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
|
||||
|
||||
@ -2892,12 +2892,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)
|
||||
return RET_PF_SPURIOUS;
|
||||
@ -2920,6 +2914,14 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
|
||||
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,
|
||||
true, host_writable, &spte);
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include <linux/memremap.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/kcore.h>
|
||||
#include <linux/bootmem_info.h>
|
||||
|
||||
@ -1017,6 +1018,9 @@ static void __meminit free_pagetable(struct page *page, int order)
|
||||
unsigned long magic;
|
||||
unsigned int nr_pages = 1 << order;
|
||||
|
||||
/* Flush IOMMU paging structure caches before freeing PT page */
|
||||
iommu_sva_invalidate_kva_range(PAGE_OFFSET, TLB_FLUSH_ALL);
|
||||
|
||||
/* bootmem page has reserved flag */
|
||||
if (PageReserved(page)) {
|
||||
__ClearPageReserved(page);
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/cc_platform.h>
|
||||
#include <linux/set_memory.h>
|
||||
#include <linux/iommu.h>
|
||||
|
||||
#include <asm/e820/api.h>
|
||||
#include <asm/processor.h>
|
||||
@ -1204,6 +1205,8 @@ static bool try_to_free_pte_page(pte_t *pte)
|
||||
if (!pte_none(pte[i]))
|
||||
return false;
|
||||
|
||||
/* Flush IOMMU paging structure caches before freeing PT page */
|
||||
iommu_sva_invalidate_kva_range(PAGE_OFFSET, TLB_FLUSH_ALL);
|
||||
free_page((unsigned long)pte);
|
||||
return true;
|
||||
}
|
||||
@ -1216,6 +1219,8 @@ static bool try_to_free_pmd_page(pmd_t *pmd)
|
||||
if (!pmd_none(pmd[i]))
|
||||
return false;
|
||||
|
||||
/* Flush IOMMU paging structure caches before freeing PT page */
|
||||
iommu_sva_invalidate_kva_range(PAGE_OFFSET, TLB_FLUSH_ALL);
|
||||
free_page((unsigned long)pmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/hugetlb.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/fixmap.h>
|
||||
@ -832,6 +833,9 @@ int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
/* INVLPG to clear all paging-structure caches */
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);
|
||||
|
||||
/* Flush IOMMU paging structure caches before freeing PT pages */
|
||||
iommu_sva_invalidate_kva_range(PAGE_OFFSET, TLB_FLUSH_ALL);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; i++) {
|
||||
if (!pmd_none(pmd_sv[i])) {
|
||||
pte = (pte_t *)pmd_page_vaddr(pmd_sv[i]);
|
||||
@ -865,6 +869,8 @@ int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
|
||||
/* INVLPG to clear all paging-structure caches */
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);
|
||||
|
||||
/* Flush IOMMU paging structure caches before freeing PT page */
|
||||
iommu_sva_invalidate_kva_range(PAGE_OFFSET, TLB_FLUSH_ALL);
|
||||
free_page((unsigned long)pte);
|
||||
|
||||
return 1;
|
||||
|
||||
@ -473,6 +473,9 @@ CONFIG_HZ=100
|
||||
CONFIG_SCHED_HRTICK=y
|
||||
CONFIG_PPC_TRANSACTIONAL_MEM=y
|
||||
CONFIG_MPROFILE_KERNEL=y
|
||||
CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY=y
|
||||
CONFIG_PPC_FTRACE_OUT_OF_LINE=y
|
||||
CONFIG_PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE=32768
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_PPC_QUEUED_SPINLOCKS=y
|
||||
CONFIG_ARCH_CPU_PROBE_RELEASE=y
|
||||
@ -663,6 +666,7 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
|
||||
CONFIG_HAVE_GCC_PLUGINS=y
|
||||
# CONFIG_GCC_PLUGINS is not set
|
||||
CONFIG_FUNCTION_ALIGNMENT=0
|
||||
CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX=y
|
||||
# end of General architecture-dependent options
|
||||
|
||||
CONFIG_RT_MUTEXES=y
|
||||
@ -4860,6 +4864,7 @@ CONFIG_HID_KUNIT_TEST=m
|
||||
#
|
||||
# HID-BPF support
|
||||
#
|
||||
CONFIG_HID_BPF=y
|
||||
# end of HID-BPF support
|
||||
|
||||
CONFIG_I2C_HID=y
|
||||
@ -6814,6 +6819,8 @@ CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y
|
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
||||
@ -6833,6 +6840,8 @@ CONFIG_FUNCTION_TRACER=y
|
||||
CONFIG_FUNCTION_GRAPH_TRACER=y
|
||||
CONFIG_DYNAMIC_FTRACE=y
|
||||
CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
|
||||
CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
|
||||
CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y
|
||||
CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y
|
||||
CONFIG_FPROBE=y
|
||||
CONFIG_FUNCTION_PROFILER=y
|
||||
@ -6856,7 +6865,7 @@ CONFIG_DYNAMIC_EVENTS=y
|
||||
CONFIG_PROBE_EVENTS=y
|
||||
# CONFIG_BPF_KPROBE_OVERRIDE is not set
|
||||
CONFIG_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_FTRACE_MCOUNT_USE_CC=y
|
||||
CONFIG_FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY=y
|
||||
CONFIG_TRACING_MAP=y
|
||||
CONFIG_SYNTH_EVENTS=y
|
||||
CONFIG_HIST_TRIGGERS=y
|
||||
|
||||
@ -2345,7 +2345,7 @@ CONFIG_SCLP_CONSOLE=y
|
||||
CONFIG_SCLP_VT220_TTY=y
|
||||
CONFIG_SCLP_VT220_CONSOLE=y
|
||||
CONFIG_HMC_DRV=m
|
||||
# CONFIG_SCLP_OFB is not set
|
||||
CONFIG_SCLP_OFB=y
|
||||
CONFIG_S390_UV_UAPI=y
|
||||
CONFIG_S390_TAPE=m
|
||||
|
||||
|
||||
@ -961,7 +961,7 @@ CONFIG_SCLP_CONSOLE=y
|
||||
CONFIG_SCLP_VT220_TTY=y
|
||||
CONFIG_SCLP_VT220_CONSOLE=y
|
||||
CONFIG_HMC_DRV=y
|
||||
# CONFIG_SCLP_OFB is not set
|
||||
CONFIG_SCLP_OFB=y
|
||||
# CONFIG_S390_UV_UAPI is not set
|
||||
# CONFIG_S390_TAPE is not set
|
||||
# CONFIG_VMCP is not set
|
||||
|
||||
@ -2368,7 +2368,7 @@ CONFIG_SCLP_CONSOLE=y
|
||||
CONFIG_SCLP_VT220_TTY=y
|
||||
CONFIG_SCLP_VT220_CONSOLE=y
|
||||
CONFIG_HMC_DRV=m
|
||||
# CONFIG_SCLP_OFB is not set
|
||||
CONFIG_SCLP_OFB=y
|
||||
CONFIG_S390_UV_UAPI=y
|
||||
CONFIG_S390_TAPE=m
|
||||
|
||||
|
||||
@ -221,6 +221,7 @@ config CRYPTO_AUTHENC
|
||||
select CRYPTO_SKCIPHER
|
||||
select CRYPTO_MANAGER
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_NULL
|
||||
help
|
||||
Authenc: Combined mode wrapper for IPsec.
|
||||
This is required for IPSec.
|
||||
@ -2131,6 +2132,7 @@ config CRYPTO_USER_API_AEAD
|
||||
depends on NET
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_SKCIPHER
|
||||
select CRYPTO_NULL
|
||||
select CRYPTO_USER_API
|
||||
help
|
||||
This option enables the user-spaces interface for AEAD
|
||||
|
||||
@ -513,8 +513,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);
|
||||
}
|
||||
@ -1133,6 +1135,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;
|
||||
@ -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.sg;
|
||||
|
||||
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,
|
||||
@ -293,7 +321,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);
|
||||
|
||||
@ -307,7 +335,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);
|
||||
@ -381,22 +409,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)
|
||||
@ -405,7 +465,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);
|
||||
@ -418,9 +479,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)
|
||||
@ -447,9 +509,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);
|
||||
|
||||
@ -82,8 +82,14 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||
* If more buffers are to be expected to be processed, process only
|
||||
* full block size buffers.
|
||||
*/
|
||||
if (ctx->more || len < ctx->used)
|
||||
if (ctx->more || len < ctx->used) {
|
||||
if (len < bs) {
|
||||
err = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
|
||||
len -= len % bs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a per request TX SGL for this request which tracks the
|
||||
|
||||
@ -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>
|
||||
@ -138,12 +139,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;
|
||||
|
||||
@ -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 {
|
||||
@ -172,6 +174,21 @@ out:
|
||||
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);
|
||||
@ -190,7 +207,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);
|
||||
}
|
||||
|
||||
@ -291,6 +311,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);
|
||||
@ -302,8 +323,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,
|
||||
@ -317,6 +344,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;
|
||||
@ -328,6 +357,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 {
|
||||
@ -162,6 +164,28 @@ static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
|
||||
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);
|
||||
@ -183,7 +207,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);
|
||||
}
|
||||
@ -218,6 +245,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;
|
||||
@ -227,8 +255,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;
|
||||
@ -298,7 +329,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;
|
||||
}
|
||||
|
||||
@ -322,6 +356,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);
|
||||
@ -333,8 +368,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 = ALIGN(2 * crypto_ahash_digestsize(auth),
|
||||
crypto_ahash_alignmask(auth) + 1);
|
||||
@ -351,6 +392,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;
|
||||
@ -362,6 +405,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)
|
||||
@ -400,6 +444,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)
|
||||
|
||||
@ -2235,12 +2235,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;
|
||||
}
|
||||
|
||||
@ -842,11 +842,21 @@ int dpll_pin_delete_ntf(struct dpll_pin *pin)
|
||||
return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
|
||||
}
|
||||
|
||||
/**
|
||||
* __dpll_pin_change_ntf - notify that the pin has been changed
|
||||
* @pin: registered pin pointer
|
||||
*
|
||||
* Context: caller must hold dpll_lock. Suitable for use inside pin
|
||||
* callbacks which are already invoked under dpll_lock.
|
||||
* Return: 0 if succeeds, error code otherwise.
|
||||
*/
|
||||
int __dpll_pin_change_ntf(struct dpll_pin *pin)
|
||||
{
|
||||
lockdep_assert_held(&dpll_lock);
|
||||
dpll_pin_notify(pin, DPLL_PIN_CHANGED);
|
||||
return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__dpll_pin_change_ntf);
|
||||
|
||||
/**
|
||||
* dpll_pin_change_ntf - notify that the pin has been changed
|
||||
|
||||
@ -11,5 +11,3 @@ int dpll_device_delete_ntf(struct dpll_device *dpll);
|
||||
int dpll_pin_create_ntf(struct dpll_pin *pin);
|
||||
|
||||
int dpll_pin_delete_ntf(struct dpll_pin *pin);
|
||||
|
||||
int __dpll_pin_change_ntf(struct dpll_pin *pin);
|
||||
|
||||
@ -983,11 +983,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);
|
||||
@ -1028,6 +1024,7 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
|
||||
"Unknown or non-match chip ID: 0x%0x\n",
|
||||
id);
|
||||
}
|
||||
zldev->chip_id = id;
|
||||
|
||||
/* Read revision, firmware version and custom config version */
|
||||
rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);
|
||||
|
||||
@ -35,6 +35,7 @@ struct zl3073x_dpll;
|
||||
* @dev: pointer to device
|
||||
* @regmap: regmap to access device registers
|
||||
* @multiop_lock: to serialize multiple register operations
|
||||
* @chip_id: chip ID read from hardware
|
||||
* @ref: array of input references' invariants
|
||||
* @out: array of outs' invariants
|
||||
* @synth: array of synths' invariants
|
||||
@ -48,6 +49,7 @@ struct zl3073x_dev {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct mutex multiop_lock;
|
||||
u16 chip_id;
|
||||
|
||||
/* Invariants */
|
||||
struct zl3073x_ref ref[ZL3073X_NUM_REFS];
|
||||
@ -144,6 +146,32 @@ 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)
|
||||
{
|
||||
switch (zldev->chip_id) {
|
||||
case 0x0E30:
|
||||
case 0x0E93:
|
||||
case 0x0E94:
|
||||
case 0x0E95:
|
||||
case 0x0E96:
|
||||
case 0x0E97:
|
||||
case 0x1F60:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
zl3073x_is_n_pin(u8 id)
|
||||
{
|
||||
@ -301,6 +329,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
|
||||
|
||||
@ -475,8 +475,11 @@ zl3073x_dpll_input_pin_phase_adjust_get(const struct dpll_pin *dpll_pin,
|
||||
ref_id = zl3073x_input_pin_ref_get(pin->id);
|
||||
ref = zl3073x_ref_state_get(zldev, ref_id);
|
||||
|
||||
/* Perform sign extension for 48bit signed value */
|
||||
phase_comp = sign_extend64(ref->phase_comp, 47);
|
||||
/* Perform sign extension based on register width */
|
||||
if (zl3073x_dev_is_ref_phase_comp_32bit(zldev))
|
||||
phase_comp = sign_extend64(ref->phase_comp, 31);
|
||||
else
|
||||
phase_comp = sign_extend64(ref->phase_comp, 47);
|
||||
|
||||
/* Reverse two's complement negation applied during set and convert
|
||||
* to 32bit signed int
|
||||
@ -916,46 +919,9 @@ zl3073x_dpll_output_pin_frequency_get(const struct dpll_pin *dpll_pin,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct zl3073x_dpll *zldpll = dpll_priv;
|
||||
struct zl3073x_dev *zldev = zldpll->dev;
|
||||
struct zl3073x_dpll_pin *pin = pin_priv;
|
||||
const struct zl3073x_synth *synth;
|
||||
const struct zl3073x_out *out;
|
||||
u32 synth_freq;
|
||||
u8 out_id;
|
||||
|
||||
out_id = zl3073x_output_pin_out_get(pin->id);
|
||||
out = zl3073x_out_state_get(zldev, out_id);
|
||||
|
||||
/* Get attached synth frequency */
|
||||
synth = zl3073x_synth_state_get(zldev, zl3073x_out_synth_get(out));
|
||||
synth_freq = zl3073x_synth_freq_get(synth);
|
||||
|
||||
switch (zl3073x_out_signal_format_get(out)) {
|
||||
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV:
|
||||
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV:
|
||||
/* In case of divided format we have to distiguish between
|
||||
* given output pin type.
|
||||
*
|
||||
* For P-pin the resulting frequency is computed as simple
|
||||
* division of synth frequency and output divisor.
|
||||
*
|
||||
* For N-pin we have to divide additionally by divisor stored
|
||||
* in esync_n_period output mailbox register that is used as
|
||||
* N-pin divisor for these modes.
|
||||
*/
|
||||
*frequency = synth_freq / out->div;
|
||||
|
||||
if (!zl3073x_dpll_is_p_pin(pin))
|
||||
*frequency = (u32)*frequency / out->esync_n_period;
|
||||
|
||||
break;
|
||||
default:
|
||||
/* In other modes the resulting frequency is computed as
|
||||
* division of synth frequency and output divisor.
|
||||
*/
|
||||
*frequency = synth_freq / out->div;
|
||||
break;
|
||||
}
|
||||
*frequency = zl3073x_dev_output_pin_freq_get(zldpll->dev, pin->id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -79,6 +79,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++;
|
||||
|
||||
@ -121,8 +121,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;
|
||||
|
||||
@ -179,9 +187,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;
|
||||
|
||||
|
||||
@ -91,6 +91,8 @@ 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;
|
||||
}
|
||||
|
||||
@ -194,6 +194,7 @@
|
||||
#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)
|
||||
|
||||
@ -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); \
|
||||
|
||||
@ -1207,10 +1207,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);
|
||||
|
||||
@ -303,9 +303,10 @@ struct i801_priv {
|
||||
|
||||
/*
|
||||
* If set to true the host controller registers are reserved for
|
||||
* ACPI AML use.
|
||||
* ACPI AML use. Needs extra protection by acpi_lock.
|
||||
*/
|
||||
bool acpi_reserved;
|
||||
struct mutex acpi_lock;
|
||||
};
|
||||
|
||||
#define FEATURE_SMBUS_PEC BIT(0)
|
||||
@ -893,8 +894,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
|
||||
int hwpec, ret;
|
||||
struct i801_priv *priv = i2c_get_adapdata(adap);
|
||||
|
||||
if (priv->acpi_reserved)
|
||||
mutex_lock(&priv->acpi_lock);
|
||||
if (priv->acpi_reserved) {
|
||||
mutex_unlock(&priv->acpi_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(&priv->pci_dev->dev);
|
||||
|
||||
@ -935,6 +939,7 @@ out:
|
||||
|
||||
pm_runtime_mark_last_busy(&priv->pci_dev->dev);
|
||||
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
|
||||
mutex_unlock(&priv->acpi_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1462,7 +1467,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
|
||||
* further access from the driver itself. This device is now owned
|
||||
* by the system firmware.
|
||||
*/
|
||||
i2c_lock_bus(&priv->adapter, I2C_LOCK_SEGMENT);
|
||||
mutex_lock(&priv->acpi_lock);
|
||||
|
||||
if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) {
|
||||
priv->acpi_reserved = true;
|
||||
@ -1482,7 +1487,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
|
||||
else
|
||||
status = acpi_os_write_port(address, (u32)*value, bits);
|
||||
|
||||
i2c_unlock_bus(&priv->adapter, I2C_LOCK_SEGMENT);
|
||||
mutex_unlock(&priv->acpi_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1542,6 +1547,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
priv->adapter.dev.parent = &dev->dev;
|
||||
acpi_use_parent_companion(&priv->adapter.dev);
|
||||
priv->adapter.retries = 3;
|
||||
mutex_init(&priv->acpi_lock);
|
||||
|
||||
priv->pci_dev = dev;
|
||||
priv->features = id->driver_data;
|
||||
|
||||
@ -220,13 +220,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);
|
||||
|
||||
@ -225,6 +225,8 @@ struct bnxt_re_dev {
|
||||
unsigned long event_bitmap;
|
||||
struct bnxt_qplib_cc_param cc_param;
|
||||
struct workqueue_struct *dcb_wq;
|
||||
struct dentry *cc_config;
|
||||
struct bnxt_re_dbg_cc_config_params *cc_config_params;
|
||||
};
|
||||
|
||||
#define to_bnxt_re_dev(ptr, member) \
|
||||
|
||||
@ -22,6 +22,23 @@
|
||||
|
||||
static struct dentry *bnxt_re_debugfs_root;
|
||||
|
||||
static const char * const bnxt_re_cc_gen0_name[] = {
|
||||
"enable_cc",
|
||||
"run_avg_weight_g",
|
||||
"num_phase_per_state",
|
||||
"init_cr",
|
||||
"init_tr",
|
||||
"tos_ecn",
|
||||
"tos_dscp",
|
||||
"alt_vlan_pcp",
|
||||
"alt_vlan_dscp",
|
||||
"rtt",
|
||||
"cc_mode",
|
||||
"tcp_cp",
|
||||
"tx_queue",
|
||||
"inactivity_cp",
|
||||
};
|
||||
|
||||
static inline const char *bnxt_re_qp_state_str(u8 state)
|
||||
{
|
||||
switch (state) {
|
||||
@ -110,19 +127,223 @@ void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
|
||||
debugfs_remove(qp->dentry);
|
||||
}
|
||||
|
||||
static int map_cc_config_offset_gen0_ext0(u32 offset, struct bnxt_qplib_cc_param *ccparam, u32 *val)
|
||||
{
|
||||
u64 map_offset;
|
||||
|
||||
map_offset = BIT(offset);
|
||||
|
||||
switch (map_offset) {
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
|
||||
*val = ccparam->enable;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
|
||||
*val = ccparam->g;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
|
||||
*val = ccparam->nph_per_state;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
|
||||
*val = ccparam->init_cr;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
|
||||
*val = ccparam->init_tr;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
|
||||
*val = ccparam->tos_ecn;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
|
||||
*val = ccparam->tos_dscp;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
|
||||
*val = ccparam->alt_vlan_pcp;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
|
||||
*val = ccparam->alt_tos_dscp;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
|
||||
*val = ccparam->rtt;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
|
||||
*val = ccparam->cc_mode;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t bnxt_re_cc_config_get(struct file *filp, char __user *buffer,
|
||||
size_t usr_buf_len, loff_t *ppos)
|
||||
{
|
||||
struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
|
||||
struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
|
||||
struct bnxt_qplib_cc_param ccparam = {};
|
||||
u32 offset = dbg_cc_param->offset;
|
||||
char buf[16];
|
||||
u32 val;
|
||||
int rc;
|
||||
|
||||
rc = bnxt_qplib_query_cc_param(&rdev->qplib_res, &ccparam);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = map_cc_config_offset_gen0_ext0(offset, &ccparam, &val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = snprintf(buf, sizeof(buf), "%d\n", val);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return simple_read_from_buffer(buffer, usr_buf_len, ppos, (u8 *)(buf), rc);
|
||||
}
|
||||
|
||||
static int bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
|
||||
{
|
||||
u32 modify_mask;
|
||||
|
||||
modify_mask = BIT(offset);
|
||||
|
||||
switch (modify_mask) {
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
|
||||
ccparam->enable = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
|
||||
ccparam->g = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
|
||||
ccparam->nph_per_state = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
|
||||
ccparam->init_cr = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
|
||||
ccparam->init_tr = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
|
||||
ccparam->tos_ecn = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
|
||||
ccparam->tos_dscp = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
|
||||
ccparam->alt_vlan_pcp = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
|
||||
ccparam->alt_tos_dscp = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
|
||||
ccparam->rtt = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
|
||||
ccparam->cc_mode = val;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
|
||||
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;
|
||||
break;
|
||||
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_PKTS_PER_PHASE:
|
||||
ccparam->pkts_pph = val;
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static ssize_t bnxt_re_cc_config_set(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
|
||||
struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
|
||||
u32 offset = dbg_cc_param->offset;
|
||||
u8 cc_gen = dbg_cc_param->cc_gen;
|
||||
char buf[16];
|
||||
u32 val;
|
||||
int rc;
|
||||
|
||||
if (count >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(buf, buffer, count))
|
||||
return -EFAULT;
|
||||
|
||||
buf[count] = '\0';
|
||||
if (kstrtou32(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
rc = bnxt_re_configure_cc(rdev, cc_gen, offset, val);
|
||||
return rc ? rc : count;
|
||||
}
|
||||
|
||||
static const struct file_operations bnxt_re_cc_config_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = bnxt_re_cc_config_get,
|
||||
.write = bnxt_re_cc_config_set,
|
||||
};
|
||||
|
||||
void bnxt_re_debugfs_add_pdev(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
struct pci_dev *pdev = rdev->en_dev->pdev;
|
||||
struct bnxt_re_dbg_cc_config_params *cc_params;
|
||||
int i;
|
||||
|
||||
rdev->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), bnxt_re_debugfs_root);
|
||||
|
||||
rdev->qp_debugfs = debugfs_create_dir("QPs", rdev->dbg_root);
|
||||
rdev->cc_config = debugfs_create_dir("cc_config", rdev->dbg_root);
|
||||
|
||||
rdev->cc_config_params = kzalloc(sizeof(*cc_params), GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < BNXT_RE_CC_PARAM_GEN0; i++) {
|
||||
struct bnxt_re_cc_param *tmp_params = &rdev->cc_config_params->gen0_parms[i];
|
||||
|
||||
tmp_params->rdev = rdev;
|
||||
tmp_params->offset = i;
|
||||
tmp_params->cc_gen = CC_CONFIG_GEN0_EXT0;
|
||||
tmp_params->dentry = debugfs_create_file(bnxt_re_cc_gen0_name[i], 0400,
|
||||
rdev->cc_config, tmp_params,
|
||||
&bnxt_re_cc_config_ops);
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
debugfs_remove_recursive(rdev->qp_debugfs);
|
||||
|
||||
debugfs_remove_recursive(rdev->cc_config);
|
||||
kfree(rdev->cc_config_params);
|
||||
debugfs_remove_recursive(rdev->dbg_root);
|
||||
rdev->dbg_root = NULL;
|
||||
}
|
||||
|
||||
@ -18,4 +18,19 @@ void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev);
|
||||
void bnxt_re_register_debugfs(void);
|
||||
void bnxt_re_unregister_debugfs(void);
|
||||
|
||||
#define CC_CONFIG_GEN_EXT(x, y) (((x) << 16) | (y))
|
||||
#define CC_CONFIG_GEN0_EXT0 CC_CONFIG_GEN_EXT(0, 0)
|
||||
|
||||
#define BNXT_RE_CC_PARAM_GEN0 14
|
||||
|
||||
struct bnxt_re_cc_param {
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct dentry *dentry;
|
||||
u32 offset;
|
||||
u8 cc_gen;
|
||||
};
|
||||
|
||||
struct bnxt_re_dbg_cc_config_params {
|
||||
struct bnxt_re_cc_param gen0_parms[BNXT_RE_CC_PARAM_GEN0];
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -6,12 +6,21 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
|
||||
#include "iommu-priv.h"
|
||||
|
||||
static DEFINE_MUTEX(iommu_sva_lock);
|
||||
static struct iommu_domain *iommu_sva_domain_alloc(struct device *dev,
|
||||
struct mm_struct *mm);
|
||||
static int iommu_sva_track_mm(struct mm_struct *mm);
|
||||
static void iommu_sva_untrack_mm(struct mm_struct *mm);
|
||||
|
||||
/* Allocate a PASID for the mm within range (inclusive) */
|
||||
static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct device *dev)
|
||||
@ -136,10 +145,20 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
|
||||
|
||||
out:
|
||||
refcount_set(&handle->users, 1);
|
||||
ret = iommu_sva_track_mm(mm);
|
||||
if (ret)
|
||||
goto out_unwind;
|
||||
mutex_unlock(&iommu_sva_lock);
|
||||
handle->dev = dev;
|
||||
return handle;
|
||||
|
||||
out_unwind:
|
||||
iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
|
||||
if (--domain->users == 0) {
|
||||
list_del(&domain->next);
|
||||
iommu_domain_free(domain);
|
||||
}
|
||||
goto out_free_handle;
|
||||
out_free_domain:
|
||||
iommu_domain_free(domain);
|
||||
out_free_handle:
|
||||
@ -170,6 +189,7 @@ void iommu_sva_unbind_device(struct iommu_sva *handle)
|
||||
return;
|
||||
}
|
||||
|
||||
iommu_sva_untrack_mm(domain->mm);
|
||||
iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
|
||||
if (--domain->users == 0) {
|
||||
list_del(&domain->next);
|
||||
@ -312,3 +332,127 @@ static struct iommu_domain *iommu_sva_domain_alloc(struct device *dev,
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
/*
|
||||
* Track mm_structs with active SVA bindings so we can flush IOMMU
|
||||
* cached translations when kernel page table pages are freed.
|
||||
*/
|
||||
struct sva_mm {
|
||||
struct mm_struct *mm;
|
||||
struct list_head list;
|
||||
struct rcu_head rcu;
|
||||
int refcount;
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(sva_mm_lock);
|
||||
static LIST_HEAD(sva_mm_list);
|
||||
static atomic_t sva_mm_count = ATOMIC_INIT(0);
|
||||
|
||||
/**
|
||||
* iommu_sva_track_mm - Start tracking an mm for kernel PT change notification
|
||||
* @mm: the mm_struct to track
|
||||
*
|
||||
* Called when SVA is bound for this mm. If the mm is already tracked,
|
||||
* increments the refcount. Otherwise allocates a new tracking entry.
|
||||
*
|
||||
* Returns 0 on success, -ENOMEM on allocation failure.
|
||||
*/
|
||||
static int iommu_sva_track_mm(struct mm_struct *mm)
|
||||
{
|
||||
struct sva_mm *smm;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sva_mm_lock, flags);
|
||||
list_for_each_entry(smm, &sva_mm_list, list) {
|
||||
if (smm->mm == mm) {
|
||||
smm->refcount++;
|
||||
spin_unlock_irqrestore(&sva_mm_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&sva_mm_lock, flags);
|
||||
|
||||
smm = kzalloc(sizeof(*smm), GFP_KERNEL);
|
||||
if (!smm)
|
||||
return -ENOMEM;
|
||||
|
||||
smm->mm = mm;
|
||||
smm->refcount = 1;
|
||||
|
||||
spin_lock_irqsave(&sva_mm_lock, flags);
|
||||
{
|
||||
struct sva_mm *existing;
|
||||
|
||||
list_for_each_entry(existing, &sva_mm_list, list) {
|
||||
if (existing->mm == mm) {
|
||||
existing->refcount++;
|
||||
spin_unlock_irqrestore(&sva_mm_lock, flags);
|
||||
kfree(smm);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
list_add_rcu(&smm->list, &sva_mm_list);
|
||||
atomic_inc(&sva_mm_count);
|
||||
spin_unlock_irqrestore(&sva_mm_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iommu_sva_untrack_mm - Stop tracking an mm for kernel PT change notification
|
||||
* @mm: the mm_struct to untrack
|
||||
*
|
||||
* Called when SVA is unbound for this mm. Decrements the refcount and
|
||||
* removes the tracking entry when it reaches zero.
|
||||
*/
|
||||
static void iommu_sva_untrack_mm(struct mm_struct *mm)
|
||||
{
|
||||
struct sva_mm *smm;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sva_mm_lock, flags);
|
||||
list_for_each_entry(smm, &sva_mm_list, list) {
|
||||
if (smm->mm == mm) {
|
||||
if (--smm->refcount == 0) {
|
||||
list_del_rcu(&smm->list);
|
||||
atomic_dec(&sva_mm_count);
|
||||
spin_unlock_irqrestore(&sva_mm_lock, flags);
|
||||
kfree_rcu(smm, rcu);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&sva_mm_lock, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&sva_mm_lock, flags);
|
||||
WARN(1, "iommu_sva_untrack_mm: mm %px not found\n", mm);
|
||||
}
|
||||
|
||||
/**
|
||||
* iommu_sva_invalidate_kva_range - Flush IOMMU caches before kernel PT free
|
||||
* @start: Start of kernel virtual address range
|
||||
* @end: End of kernel virtual address range
|
||||
*
|
||||
* Called from x86 mm code before freeing kernel page table pages.
|
||||
* Iterates all tracked SVA-bound mm_structs and calls
|
||||
* mmu_notifier_arch_invalidate_secondary_tlbs() for each, triggering
|
||||
* IOTLB flushes via the drivers' invalidate_range callbacks.
|
||||
*
|
||||
* Fast path: atomic_read() returns 0 when no SVA is active.
|
||||
*/
|
||||
void iommu_sva_invalidate_kva_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
struct sva_mm *smm;
|
||||
|
||||
if (!atomic_read(&sva_mm_count))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(smm, &sva_mm_list, list) {
|
||||
if (mmget_not_zero(smm->mm)) {
|
||||
mmu_notifier_arch_invalidate_secondary_tlbs(smm->mm, start, end);
|
||||
mmput_async(smm->mm);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@ -2476,6 +2476,7 @@ static int __bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
||||
memcpy(page_address(store.sb_page),
|
||||
page_address(bitmap->storage.sb_page),
|
||||
sizeof(bitmap_super_t));
|
||||
mutex_lock(&bitmap->mddev->bitmap_info.mutex);
|
||||
spin_lock_irq(&bitmap->counts.lock);
|
||||
md_bitmap_file_unmap(&bitmap->storage);
|
||||
bitmap->storage = store;
|
||||
@ -2583,7 +2584,7 @@ static int __bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
||||
set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY);
|
||||
}
|
||||
spin_unlock_irq(&bitmap->counts.lock);
|
||||
|
||||
mutex_unlock(&bitmap->mddev->bitmap_info.mutex);
|
||||
if (!init) {
|
||||
__bitmap_unplug(bitmap);
|
||||
bitmap->mddev->pers->quiesce(bitmap->mddev, 0);
|
||||
|
||||
@ -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)));
|
||||
|
||||
|
||||
@ -1243,6 +1243,8 @@ static int ice_devlink_reinit_up(struct ice_pf *pf)
|
||||
return err;
|
||||
}
|
||||
|
||||
ice_init_dev_hw(pf);
|
||||
|
||||
/* load MSI-X values */
|
||||
ice_set_min_max_msix(pf);
|
||||
|
||||
|
||||
@ -1162,8 +1162,6 @@ int ice_init_hw(struct ice_hw *hw)
|
||||
if (status)
|
||||
goto err_unroll_fltr_mgmt_struct;
|
||||
|
||||
ice_init_dev_hw(hw->back);
|
||||
|
||||
mutex_init(&hw->tnl_lock);
|
||||
ice_init_chk_recipe_reuse_support(hw);
|
||||
|
||||
|
||||
@ -1154,6 +1154,32 @@ ice_dpll_input_state_get(const struct dpll_pin *pin, void *pin_priv,
|
||||
extack, ICE_DPLL_PIN_TYPE_INPUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_sw_pin_notify_peer - notify the paired SW pin after a state change
|
||||
* @d: pointer to dplls struct
|
||||
* @changed: the SW pin that was explicitly changed (already notified by dpll core)
|
||||
*
|
||||
* SMA and U.FL pins share physical signal paths in pairs (SMA1/U.FL1 and
|
||||
* SMA2/U.FL2). When one pin's routing changes via the PCA9575 GPIO
|
||||
* expander, the paired pin's state may also change. Send a change
|
||||
* notification for the peer pin so userspace consumers monitoring the
|
||||
* peer via dpll netlink learn about the update.
|
||||
*
|
||||
* Context: Called from dpll_pin_ops callbacks after pf->dplls.lock is
|
||||
* released. Uses __dpll_pin_change_ntf() because dpll_lock is
|
||||
* still held by the dpll netlink layer.
|
||||
*/
|
||||
static void ice_dpll_sw_pin_notify_peer(struct ice_dplls *d,
|
||||
struct ice_dpll_pin *changed)
|
||||
{
|
||||
struct ice_dpll_pin *peer;
|
||||
|
||||
peer = (changed >= d->sma && changed < d->sma + ICE_DPLL_PIN_SW_NUM) ?
|
||||
&d->ufl[changed->idx] : &d->sma[changed->idx];
|
||||
if (peer->pin)
|
||||
__dpll_pin_change_ntf(peer->pin);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_sma_direction_set - set direction of SMA pin
|
||||
* @p: pointer to a pin
|
||||
@ -1171,6 +1197,8 @@ static int ice_dpll_sma_direction_set(struct ice_dpll_pin *p,
|
||||
enum dpll_pin_direction direction,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_dplls *d = &p->pf->dplls;
|
||||
struct ice_dpll_pin *peer;
|
||||
u8 data;
|
||||
int ret;
|
||||
|
||||
@ -1189,8 +1217,9 @@ static int ice_dpll_sma_direction_set(struct ice_dpll_pin *p,
|
||||
case ICE_DPLL_PIN_SW_2_IDX:
|
||||
if (direction == DPLL_PIN_DIRECTION_INPUT) {
|
||||
data &= ~ICE_SMA2_DIR_EN;
|
||||
data |= ICE_SMA2_UFL2_RX_DIS;
|
||||
} else {
|
||||
data &= ~ICE_SMA2_TX_EN;
|
||||
data &= ~(ICE_SMA2_TX_EN | ICE_SMA2_UFL2_RX_DIS);
|
||||
data |= ICE_SMA2_DIR_EN;
|
||||
}
|
||||
break;
|
||||
@ -1202,6 +1231,34 @@ static int ice_dpll_sma_direction_set(struct ice_dpll_pin *p,
|
||||
ret = ice_dpll_pin_state_update(p->pf, p,
|
||||
ICE_DPLL_PIN_TYPE_SOFTWARE,
|
||||
extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* When a direction change activates the paired U.FL pin, enable
|
||||
* its backing CGU pin so the pin reports as connected. Without
|
||||
* this the U.FL routing is correct but the CGU pin stays disabled
|
||||
* and userspace sees the pin as disconnected. Do not disable the
|
||||
* backing pin when U.FL becomes inactive because the SMA pin may
|
||||
* still be using it.
|
||||
*/
|
||||
peer = &d->ufl[p->idx];
|
||||
if (peer->active) {
|
||||
struct ice_dpll_pin *target;
|
||||
enum ice_dpll_pin_type type;
|
||||
|
||||
if (peer->output) {
|
||||
target = peer->output;
|
||||
type = ICE_DPLL_PIN_TYPE_OUTPUT;
|
||||
} else {
|
||||
target = peer->input;
|
||||
type = ICE_DPLL_PIN_TYPE_INPUT;
|
||||
}
|
||||
ret = ice_dpll_pin_enable(&p->pf->hw, target,
|
||||
d->eec.dpll_idx, type, extack);
|
||||
if (!ret)
|
||||
ret = ice_dpll_pin_state_update(p->pf, target,
|
||||
type, extack);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1253,6 +1310,14 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
|
||||
data &= ~ICE_SMA1_MASK;
|
||||
enable = true;
|
||||
} else if (state == DPLL_PIN_STATE_DISCONNECTED) {
|
||||
/* Skip if U.FL1 is not active, setting TX_EN
|
||||
* while DIR_EN is set would also deactivate
|
||||
* the paired SMA1 output.
|
||||
*/
|
||||
if (data & (ICE_SMA1_DIR_EN | ICE_SMA1_TX_EN)) {
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
}
|
||||
data |= ICE_SMA1_TX_EN;
|
||||
enable = false;
|
||||
} else {
|
||||
@ -1267,6 +1332,15 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
|
||||
data &= ~ICE_SMA2_UFL2_RX_DIS;
|
||||
enable = true;
|
||||
} else if (state == DPLL_PIN_STATE_DISCONNECTED) {
|
||||
/* Skip if U.FL2 is not active, setting
|
||||
* UFL2_RX_DIS could also disable the paired
|
||||
* SMA2 input.
|
||||
*/
|
||||
if (!(data & ICE_SMA2_DIR_EN) ||
|
||||
(data & ICE_SMA2_UFL2_RX_DIS)) {
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
}
|
||||
data |= ICE_SMA2_UFL2_RX_DIS;
|
||||
enable = false;
|
||||
} else {
|
||||
@ -1296,6 +1370,8 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
if (!ret)
|
||||
ice_dpll_sw_pin_notify_peer(&pf->dplls, p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1414,6 +1490,8 @@ ice_dpll_sma_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
if (!ret)
|
||||
ice_dpll_sw_pin_notify_peer(&pf->dplls, sma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1609,6 +1687,8 @@ ice_dpll_pin_sma_direction_set(const struct dpll_pin *pin, void *pin_priv,
|
||||
mutex_lock(&pf->dplls.lock);
|
||||
ret = ice_dpll_sma_direction_set(p, direction, extack);
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
if (!ret)
|
||||
ice_dpll_sw_pin_notify_peer(&pf->dplls, p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1915,7 +1995,10 @@ ice_dpll_phase_offset_get(const struct dpll_pin *pin, void *pin_priv,
|
||||
d->active_input == p->input->pin))
|
||||
*phase_offset = d->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR;
|
||||
else if (d->phase_offset_monitor_period)
|
||||
*phase_offset = p->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR;
|
||||
*phase_offset = (p->input &&
|
||||
p->direction == DPLL_PIN_DIRECTION_INPUT ?
|
||||
p->input->phase_offset :
|
||||
p->phase_offset) * ICE_DPLL_PHASE_OFFSET_FACTOR;
|
||||
else
|
||||
*phase_offset = 0;
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
@ -2614,6 +2697,27 @@ static u64 ice_generate_clock_id(struct ice_pf *pf)
|
||||
return pci_get_dsn(pf->pdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_pin_ntf - notify pin change including any SW pin wrappers
|
||||
* @dplls: pointer to dplls struct
|
||||
* @pin: the dpll_pin that changed
|
||||
*
|
||||
* Send a change notification for @pin and for any registered SMA/U.FL pin
|
||||
* whose backing CGU input matches @pin.
|
||||
*/
|
||||
static void ice_dpll_pin_ntf(struct ice_dplls *dplls, struct dpll_pin *pin)
|
||||
{
|
||||
dpll_pin_change_ntf(pin);
|
||||
for (int i = 0; i < ICE_DPLL_PIN_SW_NUM; i++) {
|
||||
if (dplls->sma[i].pin && dplls->sma[i].input &&
|
||||
dplls->sma[i].input->pin == pin)
|
||||
dpll_pin_change_ntf(dplls->sma[i].pin);
|
||||
if (dplls->ufl[i].pin && dplls->ufl[i].input &&
|
||||
dplls->ufl[i].input->pin == pin)
|
||||
dpll_pin_change_ntf(dplls->ufl[i].pin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_notify_changes - notify dpll subsystem about changes
|
||||
* @d: pointer do dpll
|
||||
@ -2622,6 +2726,7 @@ static u64 ice_generate_clock_id(struct ice_pf *pf)
|
||||
*/
|
||||
static void ice_dpll_notify_changes(struct ice_dpll *d)
|
||||
{
|
||||
struct ice_dplls *dplls = &d->pf->dplls;
|
||||
bool pin_notified = false;
|
||||
|
||||
if (d->prev_dpll_state != d->dpll_state) {
|
||||
@ -2630,17 +2735,17 @@ static void ice_dpll_notify_changes(struct ice_dpll *d)
|
||||
}
|
||||
if (d->prev_input != d->active_input) {
|
||||
if (d->prev_input)
|
||||
dpll_pin_change_ntf(d->prev_input);
|
||||
ice_dpll_pin_ntf(dplls, d->prev_input);
|
||||
d->prev_input = d->active_input;
|
||||
if (d->active_input) {
|
||||
dpll_pin_change_ntf(d->active_input);
|
||||
ice_dpll_pin_ntf(dplls, d->active_input);
|
||||
pin_notified = true;
|
||||
}
|
||||
}
|
||||
if (d->prev_phase_offset != d->phase_offset) {
|
||||
d->prev_phase_offset = d->phase_offset;
|
||||
if (!pin_notified && d->active_input)
|
||||
dpll_pin_change_ntf(d->active_input);
|
||||
ice_dpll_pin_ntf(dplls, d->active_input);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2669,6 +2774,7 @@ static bool ice_dpll_is_pps_phase_monitor(struct ice_pf *pf)
|
||||
|
||||
/**
|
||||
* ice_dpll_pins_notify_mask - notify dpll subsystem about bulk pin changes
|
||||
* @dplls: pointer to dplls struct
|
||||
* @pins: array of ice_dpll_pin pointers registered within dpll subsystem
|
||||
* @pin_num: number of pins
|
||||
* @phase_offset_ntf_mask: bitmask of pin indexes to notify
|
||||
@ -2678,15 +2784,14 @@ static bool ice_dpll_is_pps_phase_monitor(struct ice_pf *pf)
|
||||
*
|
||||
* Context: Must be called while pf->dplls.lock is released.
|
||||
*/
|
||||
static void ice_dpll_pins_notify_mask(struct ice_dpll_pin *pins,
|
||||
static void ice_dpll_pins_notify_mask(struct ice_dplls *dplls,
|
||||
struct ice_dpll_pin *pins,
|
||||
u8 pin_num,
|
||||
u32 phase_offset_ntf_mask)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < pin_num; i++)
|
||||
if (phase_offset_ntf_mask & (1 << i))
|
||||
dpll_pin_change_ntf(pins[i].pin);
|
||||
for (int i = 0; i < pin_num; i++)
|
||||
if (phase_offset_ntf_mask & BIT(i))
|
||||
ice_dpll_pin_ntf(dplls, pins[i].pin);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2862,7 +2967,7 @@ static void ice_dpll_periodic_work(struct kthread_work *work)
|
||||
ice_dpll_notify_changes(de);
|
||||
ice_dpll_notify_changes(dp);
|
||||
if (phase_offset_ntf)
|
||||
ice_dpll_pins_notify_mask(d->inputs, d->num_inputs,
|
||||
ice_dpll_pins_notify_mask(d, d->inputs, d->num_inputs,
|
||||
phase_offset_ntf);
|
||||
|
||||
resched:
|
||||
@ -4019,6 +4124,7 @@ static int ice_dpll_init_info_sw_pins(struct ice_pf *pf)
|
||||
struct ice_dpll_pin *pin;
|
||||
u32 phase_adj_max, caps;
|
||||
int i, ret;
|
||||
u8 data;
|
||||
|
||||
if (pf->hw.device_id == ICE_DEV_ID_E810C_QSFP)
|
||||
input_idx_offset = ICE_E810_RCLK_PINS_NUM;
|
||||
@ -4078,6 +4184,22 @@ static int ice_dpll_init_info_sw_pins(struct ice_pf *pf)
|
||||
}
|
||||
ice_dpll_phase_range_set(&pin->prop.phase_range, phase_adj_max);
|
||||
}
|
||||
|
||||
/* Initialize the SMA control register to a known-good default state.
|
||||
* Without this write the PCA9575 GPIO expander retains its power-on
|
||||
* default (all outputs high) which makes all SW pins appear inactive.
|
||||
* Set SMA1 and SMA2 as active inputs, disable U.FL1 output and
|
||||
* U.FL2 input.
|
||||
*/
|
||||
ret = ice_read_sma_ctrl(&pf->hw, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
data &= ~ICE_ALL_SMA_MASK;
|
||||
data |= ICE_SMA1_TX_EN | ICE_SMA2_TX_EN | ICE_SMA2_UFL2_RX_DIS;
|
||||
ret = ice_write_sma_ctrl(&pf->hw, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ice_dpll_pin_state_update(pf, pin, ICE_DPLL_PIN_TYPE_SOFTWARE,
|
||||
NULL);
|
||||
if (ret)
|
||||
|
||||
@ -5339,6 +5339,8 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
|
||||
return err;
|
||||
}
|
||||
|
||||
ice_init_dev_hw(pf);
|
||||
|
||||
adapter = ice_adapter_get(pdev);
|
||||
if (IS_ERR(adapter)) {
|
||||
err = PTR_ERR(adapter);
|
||||
|
||||
@ -1296,12 +1296,10 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
|
||||
if (pf->hw.reset_ongoing)
|
||||
return;
|
||||
|
||||
if (hw->mac_type == ICE_MAC_GENERIC_3K_E825) {
|
||||
if (hw->mac_type == ICE_MAC_GENERIC_3K_E825 &&
|
||||
test_bit(ICE_FLAG_DPLL, pf->flags)) {
|
||||
int pin, err;
|
||||
|
||||
if (!test_bit(ICE_FLAG_DPLL, pf->flags))
|
||||
return;
|
||||
|
||||
mutex_lock(&pf->dplls.lock);
|
||||
for (pin = 0; pin < ICE_SYNCE_CLK_NUM; pin++) {
|
||||
enum ice_synce_clk clk_pin;
|
||||
@ -1314,15 +1312,19 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
|
||||
port_num,
|
||||
&active,
|
||||
clk_pin);
|
||||
if (WARN_ON_ONCE(err)) {
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
return;
|
||||
if (err) {
|
||||
dev_err_once(ice_pf_to_dev(pf),
|
||||
"Failed to read SyncE bypass mux for pin %d, err %d\n",
|
||||
pin, err);
|
||||
break;
|
||||
}
|
||||
|
||||
err = ice_tspll_cfg_synce_ethdiv_e825c(hw, clk_pin);
|
||||
if (active && WARN_ON_ONCE(err)) {
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
return;
|
||||
if (active && err) {
|
||||
dev_err_once(ice_pf_to_dev(pf),
|
||||
"Failed to configure SyncE ETH divider for pin %d, err %d\n",
|
||||
pin, err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
@ -1334,9 +1336,12 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
|
||||
/* Do not reconfigure E810 or E830 PHY */
|
||||
return;
|
||||
case ICE_MAC_GENERIC:
|
||||
case ICE_MAC_GENERIC_3K_E825:
|
||||
ice_ptp_port_phy_restart(ptp_port);
|
||||
return;
|
||||
case ICE_MAC_GENERIC_3K_E825:
|
||||
if (linkup)
|
||||
ice_ptp_port_phy_restart(ptp_port);
|
||||
return;
|
||||
default:
|
||||
dev_warn(ice_pf_to_dev(pf), "%s: Unknown PHY type\n", __func__);
|
||||
}
|
||||
@ -2705,7 +2710,7 @@ static bool ice_any_port_has_timestamps(struct ice_pf *pf)
|
||||
bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
/* Check software indicator */
|
||||
switch (pf->ptp.tx_interrupt_mode) {
|
||||
@ -2726,16 +2731,19 @@ bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf)
|
||||
}
|
||||
|
||||
/* Check hardware indicator */
|
||||
for (i = 0; i < ICE_GET_QUAD_NUM(hw->ptp.num_lports); i++) {
|
||||
u64 tstamp_ready = 0;
|
||||
int err;
|
||||
|
||||
err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready);
|
||||
if (err || tstamp_ready)
|
||||
return true;
|
||||
ret = ice_check_phy_tx_tstamp_ready(hw);
|
||||
if (ret < 0) {
|
||||
dev_dbg(ice_pf_to_dev(pf), "Unable to read PHY Tx timestamp ready bitmap, err %d\n",
|
||||
ret);
|
||||
/* Stop triggering IRQs if we're unable to read PHY */
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
/* ice_check_phy_tx_tstamp_ready() returns 1 if there are timestamps
|
||||
* available, 0 if there are no waiting timestamps, and a negative
|
||||
* value if there was an error (which we checked for above).
|
||||
*/
|
||||
return ret > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2819,8 +2827,7 @@ static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf)
|
||||
{
|
||||
struct device *dev = ice_pf_to_dev(pf);
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
bool trigger_oicr = false;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (!pf->ptp.port.tx.has_ready_bitmap)
|
||||
return;
|
||||
@ -2828,21 +2835,11 @@ static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf)
|
||||
if (!ice_pf_src_tmr_owned(pf))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ICE_GET_QUAD_NUM(hw->ptp.num_lports); i++) {
|
||||
u64 tstamp_ready;
|
||||
int err;
|
||||
|
||||
err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready);
|
||||
if (!err && tstamp_ready) {
|
||||
trigger_oicr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trigger_oicr) {
|
||||
/* Trigger a software interrupt, to ensure this data
|
||||
* gets processed.
|
||||
*/
|
||||
ret = ice_check_phy_tx_tstamp_ready(hw);
|
||||
if (ret < 0) {
|
||||
dev_dbg(dev, "PTP periodic task unable to read PHY timestamp ready bitmap, err %d\n",
|
||||
ret);
|
||||
} else if (ret) {
|
||||
dev_dbg(dev, "PTP periodic task detected waiting timestamps. Triggering Tx timestamp interrupt now.\n");
|
||||
|
||||
wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
|
||||
|
||||
@ -377,6 +377,31 @@ static void ice_ptp_cfg_sync_delay(const struct ice_hw *hw, u32 delay)
|
||||
* The following functions operate on devices with the ETH 56G PHY.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ice_ptp_init_phc_e825c - Perform E825C specific PHC initialization
|
||||
* @hw: pointer to HW struct
|
||||
*
|
||||
* Perform E825C-specific PTP hardware clock initialization steps.
|
||||
*
|
||||
* Return: 0 on success, or a negative error value on failure.
|
||||
*/
|
||||
static int ice_ptp_init_phc_e825c(struct ice_hw *hw)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Soft reset all ports, to ensure everything is at a clean state */
|
||||
for (int port = 0; port < hw->ptp.num_lports; port++) {
|
||||
err = ice_ptp_phy_soft_reset_eth56g(hw, port);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to soft reset port %d, err %d\n",
|
||||
port, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_get_dest_dev_e825 - get destination PHY for given port number
|
||||
* @hw: pointer to the HW struct
|
||||
@ -1847,6 +1872,8 @@ static int ice_phy_cfg_mac_eth56g(struct ice_hw *hw, u8 port)
|
||||
* @ena: enable or disable interrupt
|
||||
* @threshold: interrupt threshold
|
||||
*
|
||||
* The threshold cannot be 0 while the interrupt is enabled.
|
||||
*
|
||||
* Configure TX timestamp interrupt for the specified port
|
||||
*
|
||||
* Return:
|
||||
@ -1858,19 +1885,45 @@ int ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold)
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
if (ena && !threshold)
|
||||
return -EINVAL;
|
||||
|
||||
err = ice_read_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val &= ~PHY_TS_INT_CONFIG_ENA_M;
|
||||
if (ena) {
|
||||
val |= PHY_TS_INT_CONFIG_ENA_M;
|
||||
val &= ~PHY_TS_INT_CONFIG_THRESHOLD_M;
|
||||
val |= FIELD_PREP(PHY_TS_INT_CONFIG_THRESHOLD_M, threshold);
|
||||
} else {
|
||||
val &= ~PHY_TS_INT_CONFIG_ENA_M;
|
||||
err = ice_write_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG,
|
||||
val);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP,
|
||||
"Failed to update 'threshold' PHY_REG_TS_INT_CONFIG port=%u ena=%u threshold=%u\n",
|
||||
port, !!ena, threshold);
|
||||
return err;
|
||||
}
|
||||
val |= PHY_TS_INT_CONFIG_ENA_M;
|
||||
}
|
||||
|
||||
return ice_write_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, val);
|
||||
err = ice_write_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, val);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP,
|
||||
"Failed to update 'ena' PHY_REG_TS_INT_CONFIG port=%u ena=%u threshold=%u\n",
|
||||
port, !!ena, threshold);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ice_read_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, &val);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP,
|
||||
"Failed to read PHY_REG_TS_INT_CONFIG port=%u ena=%u threshold=%u\n",
|
||||
port, !!ena, threshold);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2115,6 +2168,35 @@ int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_check_phy_tx_tstamp_ready_eth56g - Check Tx memory status for all ports
|
||||
* @hw: pointer to the HW struct
|
||||
*
|
||||
* Check the PHY_REG_TX_MEMORY_STATUS for all ports. A set bit indicates
|
||||
* a waiting timestamp.
|
||||
*
|
||||
* Return: 1 if any port has at least one timestamp ready bit set,
|
||||
* 0 otherwise, and a negative error code if unable to read the bitmap.
|
||||
*/
|
||||
static int ice_check_phy_tx_tstamp_ready_eth56g(struct ice_hw *hw)
|
||||
{
|
||||
int port;
|
||||
|
||||
for (port = 0; port < hw->ptp.num_lports; port++) {
|
||||
u64 tstamp_ready;
|
||||
int err;
|
||||
|
||||
err = ice_get_phy_tx_tstamp_ready(hw, port, &tstamp_ready);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (tstamp_ready)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_read_tx_hwtstamp_status_eth56g - Get TX timestamp status
|
||||
* @hw: pointer to the HW struct
|
||||
@ -2137,13 +2219,19 @@ int ice_ptp_read_tx_hwtstamp_status_eth56g(struct ice_hw *hw, u32 *ts_status)
|
||||
*ts_status = 0;
|
||||
|
||||
for (phy = 0; phy < params->num_phys; phy++) {
|
||||
u8 port;
|
||||
int err;
|
||||
|
||||
err = ice_read_phy_eth56g(hw, phy, PHY_PTP_INT_STATUS, &status);
|
||||
/* ice_read_phy_eth56g expects a port index, so use the first
|
||||
* port of the PHY
|
||||
*/
|
||||
port = phy * hw->ptp.ports_per_phy;
|
||||
|
||||
err = ice_read_phy_eth56g(hw, port, PHY_PTP_INT_STATUS, &status);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*ts_status |= (status & mask) << (phy * hw->ptp.ports_per_phy);
|
||||
*ts_status |= (status & mask) << port;
|
||||
}
|
||||
|
||||
ice_debug(hw, ICE_DBG_PTP, "PHY interrupt err: %x\n", *ts_status);
|
||||
@ -2151,6 +2239,69 @@ int ice_ptp_read_tx_hwtstamp_status_eth56g(struct ice_hw *hw, u32 *ts_status)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_phy_soft_reset_eth56g - Perform a PHY soft reset on ETH56G
|
||||
* @hw: pointer to the HW structure
|
||||
* @port: PHY port number
|
||||
*
|
||||
* Trigger a soft reset of the ETH56G PHY by toggling the soft reset
|
||||
* bit in the PHY global register. The reset sequence consists of:
|
||||
* 1. Clearing the soft reset bit
|
||||
* 2. Asserting the soft reset bit
|
||||
* 3. Clearing the soft reset bit again
|
||||
*
|
||||
* Short delays are inserted between each step to allow the hardware
|
||||
* to settle. This provides a controlled way to reinitialize the PHY
|
||||
* without requiring a full device reset.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code on failure when
|
||||
* reading or writing the PHY register.
|
||||
*/
|
||||
int ice_ptp_phy_soft_reset_eth56g(struct ice_hw *hw, u8 port)
|
||||
{
|
||||
u32 global_val;
|
||||
int err;
|
||||
|
||||
err = ice_read_ptp_reg_eth56g(hw, port, PHY_REG_GLOBAL, &global_val);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to read PHY_REG_GLOBAL for port %d, err %d\n",
|
||||
port, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
global_val &= ~PHY_REG_GLOBAL_SOFT_RESET_M;
|
||||
ice_debug(hw, ICE_DBG_PTP, "Clearing soft reset bit for port %d, val: 0x%x\n",
|
||||
port, global_val);
|
||||
err = ice_write_ptp_reg_eth56g(hw, port, PHY_REG_GLOBAL, global_val);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to write PHY_REG_GLOBAL for port %d, err %d\n",
|
||||
port, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
global_val |= PHY_REG_GLOBAL_SOFT_RESET_M;
|
||||
ice_debug(hw, ICE_DBG_PTP, "Set soft reset bit for port %d, val: 0x%x\n",
|
||||
port, global_val);
|
||||
err = ice_write_ptp_reg_eth56g(hw, port, PHY_REG_GLOBAL, global_val);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to write PHY_REG_GLOBAL for port %d, err %d\n",
|
||||
port, err);
|
||||
return err;
|
||||
}
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
global_val &= ~PHY_REG_GLOBAL_SOFT_RESET_M;
|
||||
ice_debug(hw, ICE_DBG_PTP, "Clear soft reset bit for port %d, val: 0x%x\n",
|
||||
port, global_val);
|
||||
err = ice_write_ptp_reg_eth56g(hw, port, PHY_REG_GLOBAL, global_val);
|
||||
if (err)
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to write PHY_REG_GLOBAL for port %d, err %d\n",
|
||||
port, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_phy_tx_tstamp_ready_eth56g - Read the Tx memory status register
|
||||
* @hw: pointer to the HW struct
|
||||
@ -4202,6 +4353,35 @@ ice_get_phy_tx_tstamp_ready_e82x(struct ice_hw *hw, u8 quad, u64 *tstamp_ready)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_check_phy_tx_tstamp_ready_e82x - Check Tx memory status for all quads
|
||||
* @hw: pointer to the HW struct
|
||||
*
|
||||
* Check the Q_REG_TX_MEMORY_STATUS for all quads. A set bit indicates
|
||||
* a waiting timestamp.
|
||||
*
|
||||
* Return: 1 if any quad has at least one timestamp ready bit set,
|
||||
* 0 otherwise, and a negative error value if unable to read the bitmap.
|
||||
*/
|
||||
static int ice_check_phy_tx_tstamp_ready_e82x(struct ice_hw *hw)
|
||||
{
|
||||
int quad;
|
||||
|
||||
for (quad = 0; quad < ICE_GET_QUAD_NUM(hw->ptp.num_lports); quad++) {
|
||||
u64 tstamp_ready;
|
||||
int err;
|
||||
|
||||
err = ice_get_phy_tx_tstamp_ready(hw, quad, &tstamp_ready);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (tstamp_ready)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_phy_cfg_intr_e82x - Configure TX timestamp interrupt
|
||||
* @hw: pointer to the HW struct
|
||||
@ -4755,6 +4935,23 @@ ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_check_phy_tx_tstamp_ready_e810 - Check Tx memory status register
|
||||
* @hw: pointer to the HW struct
|
||||
*
|
||||
* The E810 devices do not have a Tx memory status register. Note this is
|
||||
* intentionally different behavior from ice_get_phy_tx_tstamp_ready_e810
|
||||
* which always says that all bits are ready. This function is called in cases
|
||||
* where code will trigger interrupts if timestamps are waiting, and should
|
||||
* not be called for E810 hardware.
|
||||
*
|
||||
* Return: 0.
|
||||
*/
|
||||
static int ice_check_phy_tx_tstamp_ready_e810(struct ice_hw *hw)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* E810 SMA functions
|
||||
*
|
||||
* The following functions operate specifically on E810 hardware and are used
|
||||
@ -5009,6 +5206,21 @@ static void ice_get_phy_tx_tstamp_ready_e830(const struct ice_hw *hw, u8 port,
|
||||
*tstamp_ready |= rd32(hw, E830_PRTMAC_TS_TX_MEM_VALID_L);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_check_phy_tx_tstamp_ready_e830 - Check Tx memory status register
|
||||
* @hw: pointer to the HW struct
|
||||
*
|
||||
* Return: 1 if the device has waiting timestamps, 0 otherwise.
|
||||
*/
|
||||
static int ice_check_phy_tx_tstamp_ready_e830(struct ice_hw *hw)
|
||||
{
|
||||
u64 tstamp_ready;
|
||||
|
||||
ice_get_phy_tx_tstamp_ready_e830(hw, 0, &tstamp_ready);
|
||||
|
||||
return !!tstamp_ready;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_init_phy_e830 - initialize PHY parameters
|
||||
* @ptp: pointer to the PTP HW struct
|
||||
@ -5564,7 +5776,7 @@ int ice_ptp_init_phc(struct ice_hw *hw)
|
||||
case ICE_MAC_GENERIC:
|
||||
return ice_ptp_init_phc_e82x(hw);
|
||||
case ICE_MAC_GENERIC_3K_E825:
|
||||
return 0;
|
||||
return ice_ptp_init_phc_e825c(hw);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@ -5601,6 +5813,33 @@ int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_check_phy_tx_tstamp_ready - Check PHY Tx timestamp memory status
|
||||
* @hw: pointer to the HW struct
|
||||
*
|
||||
* Check the PHY for Tx timestamp memory status on all ports. If you need to
|
||||
* see individual timestamp status for each index, use
|
||||
* ice_get_phy_tx_tstamp_ready() instead.
|
||||
*
|
||||
* Return: 1 if any port has timestamps available, 0 if there are no timestamps
|
||||
* available, and a negative error code on failure.
|
||||
*/
|
||||
int ice_check_phy_tx_tstamp_ready(struct ice_hw *hw)
|
||||
{
|
||||
switch (hw->mac_type) {
|
||||
case ICE_MAC_E810:
|
||||
return ice_check_phy_tx_tstamp_ready_e810(hw);
|
||||
case ICE_MAC_E830:
|
||||
return ice_check_phy_tx_tstamp_ready_e830(hw);
|
||||
case ICE_MAC_GENERIC:
|
||||
return ice_check_phy_tx_tstamp_ready_e82x(hw);
|
||||
case ICE_MAC_GENERIC_3K_E825:
|
||||
return ice_check_phy_tx_tstamp_ready_eth56g(hw);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_cgu_get_pin_desc_e823 - get pin description array
|
||||
* @hw: pointer to the hw struct
|
||||
|
||||
@ -300,6 +300,7 @@ void ice_ptp_reset_ts_memory(struct ice_hw *hw);
|
||||
int ice_ptp_init_phc(struct ice_hw *hw);
|
||||
void ice_ptp_init_hw(struct ice_hw *hw);
|
||||
int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready);
|
||||
int ice_check_phy_tx_tstamp_ready(struct ice_hw *hw);
|
||||
int ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port,
|
||||
enum ice_ptp_tmr_cmd configured_cmd);
|
||||
|
||||
@ -374,6 +375,7 @@ int ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset);
|
||||
int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port);
|
||||
int ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold);
|
||||
int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port);
|
||||
int ice_ptp_phy_soft_reset_eth56g(struct ice_hw *hw, u8 port);
|
||||
|
||||
#define ICE_ETH56G_NOMINAL_INCVAL 0x140000000ULL
|
||||
#define ICE_ETH56G_NOMINAL_PCS_REF_TUS 0x100000000ULL
|
||||
@ -676,6 +678,9 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
|
||||
#define ICE_P0_GNSS_PRSNT_N BIT(4)
|
||||
|
||||
/* ETH56G PHY register addresses */
|
||||
#define PHY_REG_GLOBAL 0x0
|
||||
#define PHY_REG_GLOBAL_SOFT_RESET_M BIT(11)
|
||||
|
||||
/* Timestamp PHY incval registers */
|
||||
#define PHY_REG_TIMETUS_L 0x8
|
||||
#define PHY_REG_TIMETUS_U 0xC
|
||||
|
||||
@ -1081,6 +1081,7 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,
|
||||
|
||||
if (!size) {
|
||||
rx_buf->pagecnt_bias--;
|
||||
rx_buf->has_data = false;
|
||||
return rx_buf;
|
||||
}
|
||||
/* we are reusing so sync this buffer for CPU use */
|
||||
@ -1090,6 +1091,7 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,
|
||||
|
||||
/* We have pulled a buffer for use, so decrement pagecnt_bias */
|
||||
rx_buf->pagecnt_bias--;
|
||||
rx_buf->has_data = true;
|
||||
|
||||
return rx_buf;
|
||||
}
|
||||
@ -1302,25 +1304,15 @@ static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
|
||||
u32 idx = rx_ring->first_desc;
|
||||
u32 cnt = rx_ring->count;
|
||||
struct ice_rx_buf *buf;
|
||||
u32 xdp_frags = 0;
|
||||
int i = 0;
|
||||
|
||||
if (unlikely(xdp_buff_has_frags(xdp)))
|
||||
xdp_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags;
|
||||
|
||||
while (idx != ntc) {
|
||||
buf = &rx_ring->rx_buf[idx];
|
||||
if (++idx == cnt)
|
||||
idx = 0;
|
||||
|
||||
/* An XDP program could release fragments from the end of the
|
||||
* buffer. For these, we need to keep the pagecnt_bias as-is.
|
||||
* To do this, only adjust pagecnt_bias for fragments up to
|
||||
* the total remaining after the XDP program has run.
|
||||
*/
|
||||
if (verdict != ICE_XDP_CONSUMED)
|
||||
if (verdict != ICE_XDP_CONSUMED && buf->has_data)
|
||||
ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz);
|
||||
else if (i++ <= xdp_frags)
|
||||
else
|
||||
buf->pagecnt_bias++;
|
||||
|
||||
ice_put_rx_buf(rx_ring, buf);
|
||||
|
||||
@ -203,6 +203,7 @@ struct ice_rx_buf {
|
||||
unsigned int page_offset;
|
||||
unsigned int pgcnt;
|
||||
unsigned int pagecnt_bias;
|
||||
bool has_data;
|
||||
};
|
||||
|
||||
struct ice_q_stats {
|
||||
|
||||
@ -804,7 +804,12 @@ void ice_reset_all_vfs(struct ice_pf *pf)
|
||||
ice_vf_ctrl_invalidate_vsi(vf);
|
||||
|
||||
ice_vf_pre_vsi_rebuild(vf);
|
||||
ice_vf_rebuild_vsi(vf);
|
||||
if (ice_vf_rebuild_vsi(vf)) {
|
||||
dev_err(dev, "VF %u VSI rebuild failed, leaving VF disabled\n",
|
||||
vf->vf_id);
|
||||
mutex_unlock(&vf->cfg_lock);
|
||||
continue;
|
||||
}
|
||||
ice_vf_post_vsi_rebuild(vf);
|
||||
|
||||
ice_eswitch_attach_vf(pf, vf);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -1756,6 +1756,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;
|
||||
|
||||
@ -1354,14 +1356,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 +1435,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 +1455,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 +2270,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 +2389,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 +3046,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 +3284,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 +3328,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 +3401,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 +3474,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 +3483,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 +3516,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 +3619,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 +3727,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 +3748,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 +3759,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 +3803,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 +3813,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 +3838,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 +4321,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 +5149,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 +5182,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 +5327,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 +5361,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 +5425,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 +5437,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 +5453,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 +5587,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 +5601,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 +7883,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 +8392,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 +8414,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 +8429,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 +8746,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
|
||||
@ -10458,8 +10374,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)
|
||||
@ -10941,7 +10860,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);
|
||||
@ -11361,11 +11280,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;
|
||||
}
|
||||
|
||||
@ -11521,13 +11435,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 */
|
||||
@ -12122,11 +12029,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;
|
||||
@ -1269,10 +1268,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 +1438,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 +4372,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 +6597,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 +6604,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.
|
||||
*/
|
||||
@ -7921,6 +7917,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;
|
||||
@ -8181,11 +8179,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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -8286,7 +8301,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",
|
||||
@ -9072,9 +9090,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;
|
||||
}
|
||||
@ -5943,7 +5938,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.
|
||||
*
|
||||
@ -6117,14 +6112,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;
|
||||
}
|
||||
|
||||
@ -6217,7 +6206,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>
|
||||
@ -5172,6 +5170,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);
|
||||
@ -5288,7 +5287,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);
|
||||
@ -8451,70 +8449,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.
|
||||
@ -8598,10 +8532,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);
|
||||
@ -8893,7 +8823,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);
|
||||
@ -9176,6 +9106,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);
|
||||
@ -12515,11 +12446,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;
|
||||
@ -16547,10 +16486,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;
|
||||
@ -16566,15 +16505,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;
|
||||
}
|
||||
@ -19937,15 +19876,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,
|
||||
@ -19975,6 +19912,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;
|
||||
@ -21444,7 +21382,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;
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "14.4.0.12"
|
||||
#define LPFC_DRIVER_VERSION "14.4.0.9"
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
||||
@ -666,7 +666,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
|
||||
* Take early refcount for outstanding I/O requests we schedule during
|
||||
* delete processing for unreg_vpi. Always keep this before
|
||||
* scsi_remove_host() as we can no longer obtain a reference through
|
||||
* scsi_host_get() after scsi_remove_host as shost is set to SHOST_DEL.
|
||||
* scsi_host_get() after scsi_host_remove as shost is set to SHOST_DEL.
|
||||
*/
|
||||
if (!scsi_host_get(shost))
|
||||
return VPORT_INVAL;
|
||||
|
||||
@ -1292,7 +1292,7 @@ void qla2xxx_process_purls_iocb(void **pkt, struct rsp_que **rsp)
|
||||
a.reason = FCNVME_RJT_RC_LOGIC;
|
||||
a.explanation = FCNVME_RJT_EXP_NONE;
|
||||
xmt_reject = true;
|
||||
kfree(item);
|
||||
qla24xx_free_purex_item(item);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@ -1131,6 +1131,26 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request,
|
||||
kfree(payload);
|
||||
}
|
||||
|
||||
/*
|
||||
* The current SCSI handling on the host side does not correctly handle:
|
||||
* INQUIRY with page code 0x80, MODE_SENSE / MODE_SENSE_10 with cmd[2] == 0x1c,
|
||||
* and (for FC) MAINTENANCE_IN / PERSISTENT_RESERVE_IN passthrough.
|
||||
*/
|
||||
static bool storvsc_host_mishandles_cmd(u8 opcode, struct hv_device *device)
|
||||
{
|
||||
switch (opcode) {
|
||||
case INQUIRY:
|
||||
case MODE_SENSE:
|
||||
case MODE_SENSE_10:
|
||||
return true;
|
||||
case MAINTENANCE_IN:
|
||||
case PERSISTENT_RESERVE_IN:
|
||||
return hv_dev_is_fc(device);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void storvsc_on_io_completion(struct storvsc_device *stor_device,
|
||||
struct vstor_packet *vstor_packet,
|
||||
struct storvsc_cmd_request *request)
|
||||
@ -1141,22 +1161,12 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device,
|
||||
stor_pkt = &request->vstor_packet;
|
||||
|
||||
/*
|
||||
* The current SCSI handling on the host side does
|
||||
* not correctly handle:
|
||||
* INQUIRY command with page code parameter set to 0x80
|
||||
* MODE_SENSE and MODE_SENSE_10 command with cmd[2] == 0x1c
|
||||
* MAINTENANCE_IN is not supported by HyperV FC passthrough
|
||||
*
|
||||
* Setup srb and scsi status so this won't be fatal.
|
||||
* We do this so we can distinguish truly fatal failues
|
||||
* (srb status == 0x4) and off-line the device in that case.
|
||||
*/
|
||||
|
||||
if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
|
||||
(stor_pkt->vm_srb.cdb[0] == MODE_SENSE) ||
|
||||
(stor_pkt->vm_srb.cdb[0] == MODE_SENSE_10) ||
|
||||
(stor_pkt->vm_srb.cdb[0] == MAINTENANCE_IN &&
|
||||
hv_dev_is_fc(device))) {
|
||||
if (storvsc_host_mishandles_cmd(stor_pkt->vm_srb.cdb[0], device)) {
|
||||
vstor_packet->vm_srb.scsi_status = 0;
|
||||
vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -470,6 +470,18 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
|
||||
urb->status = rpdu->status;
|
||||
urb->actual_length = rpdu->actual_length;
|
||||
urb->start_frame = rpdu->start_frame;
|
||||
/*
|
||||
* The number_of_packets field determines the length of
|
||||
* iso_frame_desc[], which is a flexible array allocated
|
||||
* at URB creation time. A response must never claim more
|
||||
* packets than originally submitted; doing so would cause
|
||||
* an out-of-bounds write in usbip_recv_iso() and
|
||||
* usbip_pad_iso(). Clamp to zero on violation so both
|
||||
* functions safely return early.
|
||||
*/
|
||||
if (rpdu->number_of_packets < 0 ||
|
||||
rpdu->number_of_packets > urb->number_of_packets)
|
||||
rpdu->number_of_packets = 0;
|
||||
urb->number_of_packets = rpdu->number_of_packets;
|
||||
urb->error_count = rpdu->error_count;
|
||||
}
|
||||
|
||||
@ -465,7 +465,8 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
|
||||
};
|
||||
struct pnfs_layout_segment *lseg, *next;
|
||||
|
||||
set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
|
||||
if (test_and_set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags))
|
||||
return !list_empty(&lo->plh_segs);
|
||||
clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(lo->plh_inode)->flags);
|
||||
list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
|
||||
pnfs_clear_lseg_state(lseg, lseg_list);
|
||||
|
||||
@ -5815,9 +5815,14 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
||||
int len = xdr->buf->len - (op_status_offset + XDR_UNIT);
|
||||
|
||||
so->so_replay.rp_status = op->status;
|
||||
so->so_replay.rp_buflen = len;
|
||||
read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT,
|
||||
if (len <= NFSD4_REPLAY_ISIZE) {
|
||||
so->so_replay.rp_buflen = len;
|
||||
read_bytes_from_xdr_buf(xdr->buf,
|
||||
op_status_offset + XDR_UNIT,
|
||||
so->so_replay.rp_buf, len);
|
||||
} else {
|
||||
so->so_replay.rp_buflen = 0;
|
||||
}
|
||||
}
|
||||
status:
|
||||
op->status = nfsd4_map_status(op->status,
|
||||
|
||||
@ -472,11 +472,18 @@ struct nfs4_client_reclaim {
|
||||
struct xdr_netobj cr_princhash;
|
||||
};
|
||||
|
||||
/* A reasonable value for REPLAY_ISIZE was estimated as follows:
|
||||
* The OPEN response, typically the largest, requires
|
||||
* 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + 8(verifier) +
|
||||
* 4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) +
|
||||
* 20(deleg. space limit) + ~32(deleg. ace) = 112 bytes
|
||||
/*
|
||||
* REPLAY_ISIZE is sized for an OPEN response with delegation:
|
||||
* 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) +
|
||||
* 8(verifier) + 4(deleg. type) + 8(deleg. stateid) +
|
||||
* 4(deleg. recall flag) + 20(deleg. space limit) +
|
||||
* ~32(deleg. ace) = 112 bytes
|
||||
*
|
||||
* Some responses can exceed this. A LOCK denial includes the conflicting
|
||||
* lock owner, which can be up to 1024 bytes (NFS4_OPAQUE_LIMIT). Responses
|
||||
* larger than REPLAY_ISIZE are not cached in rp_ibuf; only rp_status is
|
||||
* saved. Enlarging this constant increases the size of every
|
||||
* nfs4_stateowner.
|
||||
*/
|
||||
|
||||
#define NFSD4_REPLAY_ISIZE 112
|
||||
|
||||
@ -363,6 +363,25 @@ static const struct inode_operations proc_dir_inode_operations = {
|
||||
.setattr = proc_notify_change,
|
||||
};
|
||||
|
||||
static void pde_set_flags(struct proc_dir_entry *pde)
|
||||
{
|
||||
const struct proc_ops *proc_ops = pde->proc_ops;
|
||||
|
||||
if (!proc_ops)
|
||||
return;
|
||||
|
||||
if (proc_ops->proc_flags & PROC_ENTRY_PERMANENT)
|
||||
pde->flags |= PROC_ENTRY_PERMANENT;
|
||||
if (proc_ops->proc_read_iter)
|
||||
pde->flags |= PROC_ENTRY_proc_read_iter;
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (proc_ops->proc_compat_ioctl)
|
||||
pde->flags |= PROC_ENTRY_proc_compat_ioctl;
|
||||
#endif
|
||||
if (proc_ops->proc_lseek)
|
||||
pde->flags |= PROC_ENTRY_proc_lseek;
|
||||
}
|
||||
|
||||
/* returns the registered entry, or frees dp and returns NULL on failure */
|
||||
struct proc_dir_entry *proc_register(struct proc_dir_entry *dir,
|
||||
struct proc_dir_entry *dp)
|
||||
@ -370,6 +389,9 @@ struct proc_dir_entry *proc_register(struct proc_dir_entry *dir,
|
||||
if (proc_alloc_inum(&dp->low_ino))
|
||||
goto out_free_entry;
|
||||
|
||||
if (!S_ISDIR(dp->mode))
|
||||
pde_set_flags(dp);
|
||||
|
||||
write_lock(&proc_subdir_lock);
|
||||
dp->parent = dir;
|
||||
if (pde_subdir_insert(dir, dp) == false) {
|
||||
@ -558,18 +580,6 @@ struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode,
|
||||
return p;
|
||||
}
|
||||
|
||||
static void pde_set_flags(struct proc_dir_entry *pde)
|
||||
{
|
||||
if (pde->proc_ops->proc_flags & PROC_ENTRY_PERMANENT)
|
||||
pde->flags |= PROC_ENTRY_PERMANENT;
|
||||
if (pde->proc_ops->proc_read_iter)
|
||||
pde->flags |= PROC_ENTRY_proc_read_iter;
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (pde->proc_ops->proc_compat_ioctl)
|
||||
pde->flags |= PROC_ENTRY_proc_compat_ioctl;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
|
||||
struct proc_dir_entry *parent,
|
||||
const struct proc_ops *proc_ops, void *data)
|
||||
@ -580,7 +590,6 @@ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->proc_ops = proc_ops;
|
||||
pde_set_flags(p);
|
||||
return proc_register(parent, p);
|
||||
}
|
||||
EXPORT_SYMBOL(proc_create_data);
|
||||
@ -631,7 +640,6 @@ struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
|
||||
p->proc_ops = &proc_seq_ops;
|
||||
p->seq_ops = ops;
|
||||
p->state_size = state_size;
|
||||
pde_set_flags(p);
|
||||
return proc_register(parent, p);
|
||||
}
|
||||
EXPORT_SYMBOL(proc_create_seq_private);
|
||||
@ -662,7 +670,6 @@ struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
|
||||
return NULL;
|
||||
p->proc_ops = &proc_single_ops;
|
||||
p->single_show = show;
|
||||
pde_set_flags(p);
|
||||
return proc_register(parent, p);
|
||||
}
|
||||
EXPORT_SYMBOL(proc_create_single_data);
|
||||
|
||||
@ -487,7 +487,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
|
||||
typeof_member(struct proc_ops, proc_release) release;
|
||||
struct pde_opener *pdeo;
|
||||
|
||||
if (!pde->proc_ops->proc_lseek)
|
||||
if (!pde_has_proc_lseek(pde))
|
||||
file->f_mode &= ~FMODE_LSEEK;
|
||||
|
||||
if (pde_is_permanent(pde)) {
|
||||
|
||||
@ -93,6 +93,11 @@ static inline bool pde_has_proc_compat_ioctl(const struct proc_dir_entry *pde)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool pde_has_proc_lseek(const struct proc_dir_entry *pde)
|
||||
{
|
||||
return pde->flags & PROC_ENTRY_proc_lseek;
|
||||
}
|
||||
|
||||
extern struct kmem_cache *proc_dir_entry_cache;
|
||||
void pde_free(struct proc_dir_entry *pde);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user