Import of kernel-5.14.0-687.12.1.el9_8

This commit is contained in:
almalinux-bot-kernel 2026-06-08 05:56:49 +00:00
parent 97e9ce0749
commit a19517f55f
140 changed files with 2697 additions and 1326 deletions

View File

@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-2.0
set -e
set -o pipefail
# To debug, uncomment the following line
# set -x

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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++;

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -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)");

View File

@ -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)
{

View File

@ -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);

View File

@ -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)

View File

@ -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); \

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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) \

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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),

View File

@ -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;

View File

@ -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();
}

View File

@ -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);

View File

@ -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)));

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 {

View File

@ -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);

View File

@ -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)

View File

@ -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++)

View File

@ -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];

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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,

View File

@ -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);

View File

@ -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 {

View File

@ -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

View File

@ -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);
}
/**

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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)) {

View File

@ -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