Linux Documentation
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] mm/zswap: Fix global shrinker when memory cgroup is disabled
From: Hao Jia @ 2026-07-16  2:21 UTC (permalink / raw)
  To: Yosry Ahmed
  Cc: Andrew Morton, nphamcs, tj, hannes, shakeel.butt, mhocko, mkoutny,
	chengming.zhou, muchun.song, roman.gushchin, linux-mm,
	linux-kernel, linux-doc, Hao Jia, stable
In-Reply-To: <CAO9r8zMDndmoxi_XvQv3rkkhCfb+aW3=8JdE3gAv2YOKiyiFSA@mail.gmail.com>



On 2026/7/16 00:13, Yosry Ahmed wrote:
> On Wed, Jul 15, 2026 at 5:31 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
>>
>>
>>
>> On 2026/7/15 10:31, Andrew Morton wrote:
>>> On Tue, 14 Jul 2026 09:52:59 -0700 Yosry Ahmed <yosry@kernel.org> wrote:
>>>
>>>>> When memory cgroup is disabled, mem_cgroup_iter() always returns NULL.
>>>>> Therefore, the global shrinker shrink_worker() always takes the !memcg
>>>>> branch. After MAX_RECLAIM_RETRIES empty walks, the worker simply gives up,
>>>>> so it fails to write back anything.
>>>>>
>>>>> Therefore, when memory cgroup is disabled, fall through with the !memcg
>>>>> branch and shrink the root memcg directly.
>>>>>
>>>>> With memcg disabled, shrink_memcg() only returns -ENOENT when the root
>>>>> LRU is empty, which means the total pages are already below thr. The
>>>>> loop then safely bails out via the zswap_total_pages() <= thr check.
>>>>> For any other return value from shrink_memcg(), the loop is guaranteed
>>>>> to terminate, either after MAX_RECLAIM_RETRIES failures or once the
>>>>> threshold is met.
>>>>>
>>>>> Fixes: a65b0e7607cc ("zswap: make shrinking memcg-aware")
>>>>> Cc: stable@vger.kernel.org
>>>>> Suggested-by: Nhat Pham <nphamcs@gmail.com>
>>>>> Acked-by: Nhat Pham <nphamcs@gmail.com>
>>>>> Acked-by: Yosry Ahmed <yosry@kernel.org>
>>>>> Reported-by: Yosry Ahmed <yosry@kernel.org>
>>>>> Closes: https://lore.kernel.org/all/CAO9r8zPVzMKFbCixxD-qgtRrkFxWVrHiZZeLc=eyTPKPVQgX4g@mail.gmail.com
>>>>> Signed-off-by: Hao Jia <jiahao1@lixiang.com>
>>>>
>>>> Patch 2 doesn't really depend on this one, right?
>>>>
>>>> If that's the case I think this can (and should be) picked up
>>>> separately as a hotfix. Andrew, WDYT?
>>>
>>> Please update the changelog to clearly describe the userspace-visible
>>> effects of the bug, thanks.
>>
>> I am not entirely sure if my understanding is correct here, but maybe I
>> should add something like this to the commit message?
>>
>> When cgroup_disable=memory is used (or with CONFIG_MEMCG=n), the global
>> shrinker fails to write back any pages. Consequently, the zswap pool
>> fills up to its limit and rejects further storage, preventing memory
>> pressure from being offloaded to the backing swap device.
> 
> I think you can simply write that zswap writeback when the limit is
> hit is broken when memcg is disabled.
Will do. Thanks!

> 
>>
>>> Also, AI review has flagged several possible issues, all appear to be
>>> serious:
>>>        https://sashiko.dev/#/patchset/20260714081510.16895-1-jiahao.kernel@gmail.com
>>
>> For AI review comments on this patch:
>> I suspect this scenario might only exist in theory. For zswap LRU to be
>> empty while zswap_total_pages() > thr holds true, it would require a
>> prolonged state where there are always more than thr zswap entries on
>> the zswap LRU whenever zswap_total_pages() > thr is evaluated, yet the
>> zswap LRU happens to be empty during shrink_memcg(root_memcg).
>>
>> If we want to fix this, perhaps we could do something like this?
>>
>> Yosry, Nhat, what are your thoughts on this?
> 
> Do we need to do this? The last paragraph in your changelog explains
> why this can't happen because zswap_total_pages() should be 0 in this
> case. Did I miss something?

The loop would require the following sequence to repeat indefinitely:

1、zswap_total_pages() > thr evaluates to true.
2、During shrink_memcg(root_memcg), the zswap LRU is concurrently drained 
to empty.
3、Before zswap_total_pages() > thr is evaluated again, the zswap LRU is 
heavily refilled such that zswap_total_pages() > thr holds true once more.

For our case to manifest, it would require zswap_total_pages() and the 
zswap LRU state to repeatedly hit this exact window with perfect 
alignment over a **prolonged period**. Therefore, I suspect this 
scenario might only exist in theory.

Thanks,
Hao

^ permalink raw reply

* [PATCH 4/4] docs: pt_BR: Translate deprecated interfaces guide to Portuguese
From: Daniel Pereira @ 2026-07-16  2:10 UTC (permalink / raw)
  To: corbet; +Cc: linux-doc, Daniel Pereira
In-Reply-To: <20260716021013.48025-1-danielmaraboo@gmail.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 22877 bytes --]

Translate the deprecated interfaces, language features, attributes, and
conventions document (deprecated.rst) to Portuguese (pt_BR).

This ensures Portuguese-speaking developers have access to local guidelines
on deprecated APIs (like BUG(), strcpy(), and VLAs), correct usage of
safe alternatives (like WARN(), strscpy(), and flexible array members),
and modern object allocator macros (kmalloc_obj).

Signed-off-by: Daniel Pereira <danielmaraboo@gmail.com>
---
 Documentation/translations/pt_BR/index.rst    |   2 +-
 .../translations/pt_BR/process/deprecated.rst | 422 ++++++++++++++++++
 2 files changed, 423 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/translations/pt_BR/process/deprecated.rst

diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst
index 5911442f6..d2a75f5de 100644
--- a/Documentation/translations/pt_BR/index.rst
+++ b/Documentation/translations/pt_BR/index.rst
@@ -86,5 +86,5 @@ kernel e sobre como ver seu trabalho integrado.
    Lista de verificação para submissão de patches do kernel Linux <process/submit-checklist>
    Interpretação do Código de Conduta do Kernel Linux <process/code-of-conduct-interpretation>
    Código de Conduta de Compromisso do Colaborador <process/code-of-conduct>
-
+   Interfaces, recursos de linguagem, atributos e convenções obsoletos <process/deprecated>
 
diff --git a/Documentation/translations/pt_BR/process/deprecated.rst b/Documentation/translations/pt_BR/process/deprecated.rst
new file mode 100644
index 000000000..2793a1fc9
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/deprecated.rst
@@ -0,0 +1,422 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========================================================================
+Interfaces, recursos de linguagem, atributos e convenções obsoletos
+========================================================================
+
+Em um mundo perfeito, seria possível converter todas as instâncias de alguma
+API obsoleta para a nova API e remover completamente a API antiga em um único
+ciclo de desenvolvimento. No entanto, devido ao tamanho do kernel, à hierarquia
+de manutenção e ao cronograma, nem sempre é viável realizar esse tipo de
+conversão de uma só vez. Isso significa que novas instâncias podem acabar
+entrando no kernel enquanto as antigas estão sendo removidas, apenas aumentando
+o volume de trabalho para remover a API. A fim de instruir os desenvolvedores
+sobre o que se tornou obsoleto e o porquê, esta lista foi criada para servir de
+referência quando o uso de elementos obsoletos for proposto para inclusão no
+kernel.
+
+__deprecated
+------------
+Embora este atributo marque visualmente uma interface como obsoleta, ele `não
+gera mais avisos durante as compilações
+<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_ porque
+um dos objetivos permanentes do kernel é compilar sem avisos (*warnings*), e
+ninguém estava de fato agindo para remover essas interfaces obsoletas. Embora o
+uso de `__deprecated` seja útil para sinalizar uma API antiga em um arquivo de
+cabeçalho (*header file*), não é a solução completa. Tais interfaces devem ser
+totalmente removidas do kernel ou adicionadas a este arquivo para desestimular
+outros desenvolvedores de usá-las no futuro.
+
+BBUG() e BUG_ON()
+-----------------
+Em vez disso, use WARN() e WARN_ON() e trate a condição de erro "impossível"
+da forma mais amigável possível. Embora a família de APIs BUG() tenha sido
+originalmente projetada para agir como uma asserção de "situação impossível" e
+eliminar uma thread do kernel de forma "segura", ela se mostrou arriscada
+demais. (Por exemplo: "Em que ordem os bloqueios precisam ser liberados? Os
+diversos estados foram restaurados?") Muito frequentemente, o uso de BUG() vai
+desestabilizar o sistema ou travá-lo por completo, o que torna impossível
+depurar ou até mesmo obter relatórios de travamento (*crash reports*) viáveis.
+Linus tem opiniões `muito fortes
+<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_
+`sobre isso
+<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_.
+
+Note que a família WARN() só deve ser usada para situações que "espera-se que
+sejam inacessíveis". Se você quiser alertar sobre situações que são
+"acessíveis, mas indesejáveis", use a família de funções pr_warn(). Os
+administradores do sistema podem ter configurado o sysctl *panic_on_warn* para
+garantir que seus sistemas não continuem executando diante de condições
+"inacessíveis". (Para exemplos, veja commits como `este aqui
+<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_.)
+
+Aritmética explícita em argumentos do alocador
+----------------------------------------------
+Cálculos dinâmicos de tamanho (especialmente multiplicação) não devem ser
+realizados em argumentos de funções de alocação de memória (ou similares)
+devido ao risco de estouro de capacidade (*overflow*). Isso poderia fazer com
+que os valores dessem a volta (*wrap around*), resultando em uma alocação menor
+do que o esperado pelo chamador. O uso dessas alocações pode levar a estouros
+lineares na memória heap e a outros comportamentos incorretos. (Uma exceção a
+isso são valores literais onde o compilador pode emitir um aviso se houver
+risco de estouro. No entanto, a maneira preferível nesses casos é refatorar o
+código conforme sugerido abaixo para evitar a aritmética explícita.)
+
+Por exemplo, não use ``count * size`` como argumento, como em::
+
+        foo = kmalloc(count * size, GFP_KERNEL);
+
+Em vez disso, a forma de dois fatores do alocador deve ser utilizada::
+
+        foo = kmalloc_array(count, size, GFP_KERNEL);
+
+Especificamente, kmalloc() pode ser substituído por kmalloc_array(), e
+kzalloc() pode ser substituído por kcalloc().
+
+Se nenhuma forma de dois fatores estiver disponível, os auxiliares de
+saturação em estouro (*saturate-on-overflow*) devem ser usados::
+
+        bar = dma_alloc_coherent(dev, array_size(count, size), &dma, GFP_KERNEL);
+
+Outro caso comum a ser evitado é calcular o tamanho de uma estrutura com uma
+matriz final de outras estruturas, como em::
+
+        header = kzalloc(sizeof(*header) + count * sizeof(*header->item),
+                         GFP_KERNEL);
+
+Em vez disso, use o auxiliar::
+
+        header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
+
+.. note:: Se você estiver usando struct_size() em uma estrutura que contém uma
+        matriz de comprimento zero ou de um único elemento como membro final,
+        refatore o uso dessa matriz e mude para um `membro de matriz flexível
+        <#zero-length-and-one-element-arrays>`_ em seu lugar.
+
+Para outros cálculos, faça a composição usando os auxiliares size_mul(),
+size_add() e size_sub(). Por exemplo, no caso de::
+
+        foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL);
+
+Em vez disso, use os auxiliares::
+
+        foo = krealloc(size_add(current_size,
+                                size_mul(chunk_size,
+                                         size_sub(count, 3))), GFP_KERNEL);
+
+Para mais detalhes, veja também array3_size() e flex_array_size(), bem como as
+funções relacionadas das famílias check_mul_overflow(), check_add_overflow(),
+check_sub_overflow() e check_shl_overflow().\
+
+simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
+----------------------------------------------------------------------
+As funções simple_strtol(), simple_strtoll(), simple_strtoul() e
+simple_strtoull() ignoram explicitamente estouros de capacidade (*overflows*),
+o que pode levar a resultados inesperados nos chamadores. As respectivas
+funções kstrtol(), kstrtoll(), kstrtoul() e kstrtoull() tendem a ser as
+substitutas corretas, embora se deva notar que estas exigem que a string seja
+terminada em NUL ou em nova linha (*newline*).
+
+strcpy()
+--------
+A função strcpy() não realiza verificação de limites no buffer de destino.
+Isso pode resultar em estouros lineares além do final do buffer, levando a todo
+tipo de comportamentos incorretos. Embora ``CONFIG_FORTIFY_SOURCE=y`` e várias
+opções do compilador ajudem a reduzir o risco de usar esta função, não há uma
+boa razão para adicionar novos usos dela. A substituta segura é strscpy(),
+embora se deva ter cuidado nos casos em que o valor de retorno de strcpy() era
+utilizado, já que strscpy() não retorna um ponteiro para o destino, mas sim a
+quantidade de bytes não-NUL copiados (ou um código de erro errno negativo quando
+ocorre truncamento).
+
+strncpy()
+---------
+A função strncpy() foi removida do kernel. Todos os chamadores antigos foram
+migrados para alternativas mais seguras.
+
+A função strncpy() não garantia a terminação em NUL do buffer de destino,
+levando a estouros de leitura linear e outros comportamentos incorretos. Ela
+também preenchia incondicionalmente o destino com NUL, o que representava uma
+penalidade de desempenho desnecessária para chamadores que usavam apenas
+strings terminadas em NUL. Devido aos seus diversos comportamentos, ela era uma
+API ambígua para determinar qual era a real intenção do autor ao realizar a
+cópia.
+
+As substitutas para strncpy() são:
+
+- strscpy() quando o destino deve ser terminado em NUL.
+- strscpy_pad() quando o destino deve ser terminado em NUL e preenchido com
+  zeros (por exemplo, estruturas que cruzam fronteiras de privilégio).
+- memtostr() para destinos terminados em NUL a partir de origens de largura
+  fixa não terminadas em NUL (com o atributo ``__nonstring`` na origem).
+- memtostr_pad() para o mesmo caso anterior, mas com preenchimento de zeros.
+- strtomem() para destinos de largura fixa não terminados em NUL, com o
+  atributo ``__nonstring`` no destino.
+- strtomem_pad() para destinos não terminados em NUL que também precisam de
+  preenchimento com zeros.
+- memcpy_and_pad() para cópias limitadas a partir de origens potencialmente não
+  terminadas, onde o tamanho do destino é um valor definido em tempo de
+  execução (*runtime*).
+
+strlcpy()
+---------
+A função strlcpy() lê primeiro todo o buffer de origem (já que o valor de
+retorno deve corresponder ao de strlen()). Essa leitura pode exceder o limite
+de tamanho do destino. Isso é ineficiente e pode levar a estouros de leitura
+linear se a string de origem não for terminada em NUL. A substituta segura é
+strscpy(), embora se deva ter cuidado nos casos em que o valor de retorno de
+strlcpy() é utilizado, já que strscpy() retornará valores negativos de errno
+quando houver truncamento.
+
+Especificador de formato %p
+----------------------------
+Tradicionalmente, o uso de "%p" em strings de formatação causava falhas de
+exposição de endereços reais no dmesg, proc, sysfs, etc. Em vez de deixar esses
+endereços expostos a explorações, todos os usos de "%p" no kernel agora são
+exibidos como um valor hash, tornando-os inúteis para fins de endereçamento.
+Novos usos de "%p" não devem ser adicionados ao kernel. Para endereços de texto,
+usar "%pS" costuma ser melhor, pois exibe o nome do símbolo, que é muito mais
+útil. Para quase todo o restante, simplesmente não adicione "%p" de forma
+alguma.
+
+Parafraseando as diretrizes atuais do Linus `guidance
+<https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_:
+
+- Se o valor hash de "%p" é inútil, pergunte a si mesmo se o ponteiro em si é
+  importante. Talvez ele deva ser removido por completo?
+- Se você realmente acredita que o valor real do ponteiro é importante, por que
+  algum estado do sistema ou nível de privilégio do usuário seria considerado
+  "especial"? Se você acha que pode justificar isso (em comentários e no log de
+  commit) de forma sólida o suficiente para resistir ao escrutínio do Linus,
+  talvez possa usar "%px", certificando-se de aplicar permissões adequadas.
+
+Se você estiver depurando algo em que a geração de hash de "%p" esteja causando
+problemas, é possível inicializar o sistema temporariamente com a opção de
+depuração "`no_hash_pointers
+<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_".
+
+Matrizes de Tamanho Variável (VLAs)
+-----------------------------------
+O uso de VLAs (Variable Length Arrays) na pilha de execução gera um código de
+máquina muito pior do que matrizes de tamanho estático na pilha. Embora esses
+problemas significativos de `desempenho
+<https://git.kernel.org/linus/02361bc77888>`_ sejam motivo suficiente para
+eliminar as VLAs, elas também representam um risco de segurança. O crescimento
+dinâmico de uma matriz na pilha pode exceder a memória restante no segmento da
+pilha. Isso pode levar a um travamento, à possível sobrescrita de dados
+sensíveis no final da pilha (quando compilado sem ``CONFIG_THREAD_INFO_IN_TASK=y``)
+ou à sobrescrita de posições de memória adjacentes à pilha (quando compilado sem
+``CONFIG_VMAP_STACK=y``).
+
+Passagem direta implícita no switch case (fall-through)
+-------------------------------------------------------
+A linguagem C permite que o fluxo de execução de um bloco switch passe
+diretamente para o próximo caso (fall-through) quando uma instrução "break"
+está ausente ao final de um caso. No entanto, isso introduz ambiguidade no
+código, pois nem sempre fica claro se o "break" ausente é intencional ou um bug.
+Por exemplo, não é óbvio apenas olhando para o código se o ``STATE_ONE`` foi
+intencionalmente projetado para passar diretamente para o ``STATE_TWO``::
+
+        switch (value) {
+        case STATE_ONE:
+                do_something();
+        case STATE_TWO:
+                do_other();
+                break;
+        default:
+                WARN("unknown state");
+        }
+
+Como há uma longa lista de falhas `causadas pela ausência de instruções "break"
+<https://cwe.mitre.org/data/definitions/484.html>`_, não permitimos mais a
+passagem direta implícita. Para identificar os casos de passagem direta
+intencionais, adotamos a macro pseudo-palavra-chave "fallthrough", que se
+expande para a extensão do gcc `__attribute__((__fallthrough__))
+<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_. (Quando a
+sintaxe ``[[fallthrough]]`` do C17/C18 for suportada de forma mais ampla por
+compiladores C, analisadores estáticos e IDEs, poderemos mudar para o uso dessa
+sintaxe para a pseudo-palavra-chave da macro.)
+
+Todos os blocos de switch/case devem terminar com um dos seguintes elementos:
+
+* break;
+* fallthrough;
+* continue;
+* goto <rótulo>;
+* return [expressão];
+
+Matrizes de comprimento zero e de um único elemento
+----------------------------------------------------
+Há uma necessidade frequente no kernel de fornecer uma maneira de declarar uma
+estrutura com um conjunto de elementos finais de tamanho dinâmico. O código do
+kernel deve sempre usar `"membros de matriz flexível"
+<https://en.wikipedia.org/wiki/Flexible_array_member>`_ para esses casos. O
+estilo antigo de matrizes de um único elemento ou de comprimento zero não deve
+mais ser utilizado.
+
+No código C mais antigo, elementos finais de tamanho dinâmico eram declarados
+especificando uma matriz de um elemento ao final de uma estrutura::
+
+        struct something {
+                size_t count;
+                struct foo items[1];
+        };
+
+Isso levava a cálculos de tamanho frágeis via sizeof() (que exigiam a subtração
+do tamanho do elemento final único para obter o tamanho correto do "cabeçalho").
+Uma `extensão GNU C <https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ foi
+introduzida para permitir matrizes de comprimento zero, a fim de evitar esses
+problemas de cálculo de tamanho::
+
+        struct something {
+                size_t count;
+                struct foo items[0];
+        };
+
+No entanto, isso trouxe outros problemas e não resolveu algumas limitações de
+ambos os estilos, como a incapacidade de detectar quando tal matriz é usada
+acidentalmente *fora* do final de uma estrutura (o que poderia ocorrer
+diretamente, ou quando tal estrutura estava contida em unions, estruturas de
+estruturas, etc.).
+
+O padrão C99 introduziu os "membros de matriz flexível", nos quais a declaração
+da matriz simplesmente não possui um tamanho numérico::
+
+        struct something {
+                size_t count;
+                struct foo items[];
+        };
+
+Esta é a maneira como o kernel espera que elementos finais de tamanho dinâmico
+sejam declarados. Isso permite que o compilador gere erros quando a matriz
+flexível não for o último elemento da estrutura, o que ajuda a evitar que bugs
+de `comportamento indefinido
+<https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_ sejam
+introduzidos inadvertidamente na base de código. Também permite que o
+compilador analise corretamente os tamanhos das matrizes (via sizeof(),
+``CONFIG_FORTIFY_SOURCE`` e ``CONFIG_UBSAN_BOUNDS``). Por exemplo, não existe um
+mecanismo que nos alerte de que a seguinte aplicação do operador sizeof() a uma
+matriz de comprimento zero sempre resulta em zero::
+
+        struct something {
+                size_t count;
+                struct foo items[0];
+        };
+
+        struct something *instance;
+
+        instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
+        instance->count = count;
+
+        size = sizeof(instance->items) * instance->count;
+        memcpy(instance->items, source, size);
+
+Na última linha do código acima, ``size`` acaba sendo ``zero``, quando se
+poderia pensar que ele representaria o tamanho total em bytes da memória
+dinâmica recentemente alocada para a matriz final ``items``. Aqui estão alguns
+exemplos deste problema: `link 1
+<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_,
+`link 2
+<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_.
+Em vez disso, `membros de matriz flexível têm tipo incompleto e, portanto, o
+operador sizeof() não pode ser aplicado
+<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, de modo que qualquer
+uso incorreto de tais operadores será imediatamente percebido em tempo de
+compilação.
+
+Em relação às matrizes de um único elemento, é preciso estar muito ciente de que
+`tais matrizes ocupam pelo menos o mesmo espaço que um único objeto daquele tipo
+<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ e, portanto, contribuem
+para o tamanho da estrutura que as contém. Isso é propício a erros sempre que se
+deseja calcular o tamanho total da memória dinâmica a ser alocada para uma
+estrutura que contém uma matriz desse tipo como membro::
+
+        struct something {
+                size_t count;
+                struct foo items[1];
+        };
+
+        struct something *instance;
+
+        instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL);
+        instance->count = count;
+
+        size = sizeof(instance->items) * instance->count;
+        memcpy(instance->items, source, size);
+
+No exemplo acima, foi necessário lembrar de calcular ``count - 1`` ao usar o
+auxiliar struct_size(); caso contrário, teríamos alocado memória --de forma não
+intencional-- para um objeto ``items`` a mais. A maneira mais limpa e menos
+sujeita a erros de implementar isso é através do uso de um `membro de matriz
+flexível`, em conjunto com os auxiliares struct_size() e flex_array_size()::
+
+        struct something {
+                size_t count;
+                struct foo items[];
+        };
+
+        struct something *instance;
+
+        instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
+        instance->count = count;
+
+        memcpy(instance->items, source, flex_array_size(instance, items, instance->count));
+
+Existem dois casos especiais de substituição nos quais o auxiliar
+DECLARE_FLEX_ARRAY() precisa ser utilizado. (Note que ele é nomeado
+__DECLARE_FLEX_ARRAY() para uso em cabeçalhos de UAPI.) Esses casos ocorrem
+quando a matriz flexível está sozinha em uma estrutura ou faz parte de uma
+union. Isso não é permitido pela especificação C99, mas sem justificativa
+técnica (como pode ser visto tanto pelo uso existente de tais matrizes nesses
+locais quanto pela solução alternativa que DECLARE_FLEX_ARRAY() adota). Por
+exemplo, para converter isto::
+
+        struct something {
+                ...
+                union {
+                        struct type1 one[0];
+                        struct type2 two[0];
+                };
+        };
+
+O auxiliar deve ser utilizado::
+
+        struct something {
+                ...
+                union {
+                        DECLARE_FLEX_ARRAY(struct type1, one);
+                        DECLARE_FLEX_ARRAY(struct type2, two);
+                };
+        };
+
+Atribuições diretas de kmalloc para objetos struct
+--------------------------------------------------
+Realizar atribuições diretas (*open-coded*) de alocações da família kmalloc()
+impede que o kernel (e o compilador) consigam examinar o tipo da variável que
+está recebendo a atribuição, o que limita qualquer introspecção relacionada que
+possa ajudar com alinhamento, estouros de capacidade (*wrap-around*) ou
+proteções adicionais (*hardening*). A família de macros kmalloc_obj() fornece
+essa introspecção, que pode ser usada para os padrões de código comuns de
+alocações de objetos únicos, de matrizes ou de objetos flexíveis. Por exemplo,
+estas atribuições diretas::
+
+        ptr = kmalloc(sizeof(*ptr), gfp);
+        ptr = kzalloc(sizeof(*ptr), gfp);
+        ptr = kmalloc_array(count, sizeof(*ptr), gfp);
+        ptr = kcalloc(count, sizeof(*ptr), gfp);
+        ptr = kmalloc(struct_size(ptr, flex_member, count), gfp);
+        ptr = kmalloc(sizeof(struct foo), gfp);
+
+tornam-se, respectivamente::
+
+        ptr = kmalloc_obj(*ptr [, gfp] );
+        ptr = kzalloc_obj(*ptr [, gfp] );
+        ptr = kmalloc_objs(*ptr, count [, gfp] );
+        ptr = kzalloc_objs(*ptr, count [, gfp] );
+        ptr = kmalloc_flex(*ptr, flex_member, count [, gfp] );
+        __auto_type ptr = kmalloc_obj(struct foo [, gfp] );
+
+O argumento gfp é opcional, sendo o valor padrão GFP_KERNEL. Se
+``ptr->flex_member`` estiver anotado com __counted_by(), a alocação falhará
+automaticamente caso ``count`` seja maior do que o valor máximo representável
+que pode ser armazenado no membro contador associado a ``flex_member``.
-- 
2.47.3


^ permalink raw reply related

* [PATCH 3/4] docs: pt_BR: Translate Code of Conduct to Portuguese
From: Daniel Pereira @ 2026-07-16  2:10 UTC (permalink / raw)
  To: corbet; +Cc: linux-doc, Daniel Pereira
In-Reply-To: <20260716021013.48025-1-danielmaraboo@gmail.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 5427 bytes --]

Translate the Contributor Covenant Code of Conduct document from
Documentation/process/code-of-conduct.rst to Portuguese (pt_BR)
to ensure the community guidelines are accessible in the local
language.

Also, add the newly translated file to the main index in the pt_BR
translation directory to ensure it compiles correctly within the
Sphinx build.

Signed-off-by: Daniel Pereira <danielmaraboo@gmail.com>
---
 Documentation/translations/pt_BR/index.rst    |  3 +
 .../pt_BR/process/code-of-conduct.rst         | 88 +++++++++++++++++++
 2 files changed, 91 insertions(+)
 create mode 100644 Documentation/translations/pt_BR/process/code-of-conduct.rst

diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst
index d9276a8dc..5911442f6 100644
--- a/Documentation/translations/pt_BR/index.rst
+++ b/Documentation/translations/pt_BR/index.rst
@@ -85,3 +85,6 @@ kernel e sobre como ver seu trabalho integrado.
    Adicionando uma nova chamada de Sistema <process/adding-syscalls>
    Lista de verificação para submissão de patches do kernel Linux <process/submit-checklist>
    Interpretação do Código de Conduta do Kernel Linux <process/code-of-conduct-interpretation>
+   Código de Conduta de Compromisso do Colaborador <process/code-of-conduct>
+
+
diff --git a/Documentation/translations/pt_BR/process/code-of-conduct.rst b/Documentation/translations/pt_BR/process/code-of-conduct.rst
new file mode 100644
index 000000000..1ab171bf2
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/code-of-conduct.rst
@@ -0,0 +1,88 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _pt_BR_code_of_conduct:
+
+Código de Conduta de Compromisso do Colaborador
++++++++++++++++++++++++++++++++++++++++++++++++
+
+Nosso Compromisso
+=================
+
+No interesse de promover um ambiente aberto e acolhedor, nós, como colaboradores
+e mantenedores, nos comprometemos a tornar a participação em nosso projeto e em
+nossa comunidade uma experiência livre de assédio para todos, independentemente
+da idade, tamanho corporal, deficiência, etnia, características sexuais,
+identidade e expressão de gênero, nível de experiência, educação, status
+socioeconômico, nacionalidade, aparência pessoal, raça, religião ou identidade
+e orientação sexual.
+
+Nossos Padrões
+==============
+
+Exemplos de comportamentos que contribuem para a criação de um ambiente positivo
+incluem:
+
+* Utilizar linguagem acolhedora e inclusiva
+* Respeitar pontos de vista e experiências divergentes
+* Aceitar críticas construtivas de forma cortês
+* Focar no que é melhor para a comunidade
+* Demonstrar empatia para com outros membros da comunidade
+
+Exemplos de comportamentos inaceitáveis por parte dos participantes incluem:
+
+* O uso de linguagem ou imagens de teor sexual, bem como atenção ou avanços
+  sexuais indesejados
+* Provocações (*trolling*), comentários insultuosos/depreciativos e ataques
+  pessoais ou políticos
+* Assédio público ou privado
+* Publicar informações privadas de terceiros, como endereço físico ou eletrônico,
+  sem permissão explícita
+* Qualquer outra conduta que possa ser razoavelmente considerada inadequada em um
+  ambiente profissional
+
+Nossas Responsabilidades
+========================
+
+Os mantenedores são responsáveis por esclarecer os padrões de comportamento
+aceitável e devem tomar medidas corretivas apropriadas e justas em resposta a
+quaisquer casos de comportamento inaceitável.
+
+Os mantenedores têm o direito e a responsabilidade de remover, editar ou rejeitar
+comentários, commits, código, edições em wiki, issues e outras contribuições que
+não estejam alinhadas a este Código de Conduta, ou de banir temporária ou
+permanentemente qualquer colaborador por outros comportamentos que considerem
+inadequados, ameaçadores, ofensivos ou prejudiciais.
+
+Escopo
+======
+
+Este Código de Conduta se aplica tanto dentro dos espaços do projeto quanto em
+espaços públicos quando um indivíduo estiver representando o projeto ou sua
+comunidade. Exemplos de representação do projeto ou comunidade incluem o uso de um
+endereço de e-mail oficial do projeto, publicações por meio de uma conta oficial
+em redes sociais ou atuar como um representante nomeado em um evento online ou
+presencial. A representação de um projeto pode ser detalhada e esclarecida de forma
+adicional pelos mantenedores do projeto.
+
+Aplicação
+=========
+
+Casos de comportamento abusivo, de assédio ou inaceitável sob qualquer outro aspecto
+podem ser relatados entrando em contato com o Comitê do Código de Conduta pelo e-mail
+<conduct@kernel.org>. Todas as reclamações serão revisadas e investigadas, resultando
+em uma resposta considerada necessária e adequada às circunstâncias. O Comitê do
+Código de Conduta é obrigado a manter a confidencialidade em relação ao denunciante
+de um incidente. Detalhes adicionais sobre políticas de aplicação específicas podem
+ser publicados separadamente.
+
+Atribuição
+==========
+
+Este Código de Conduta foi adaptado do Contributor Covenant, versão 1.4,
+disponível em https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+Interpretação
+=============
+
+Consulte o documento :ref:`code_of_conduct_interpretation` para entender como a
+comunidade do kernel Linux interpretará este documento.
-- 
2.47.3


^ permalink raw reply related

* [PATCH 2/4] docs: pt_BR: Translate code-of-conduct-interpretation to Portuguese
From: Daniel Pereira @ 2026-07-16  2:10 UTC (permalink / raw)
  To: corbet; +Cc: linux-doc, Daniel Pereira
In-Reply-To: <20260716021013.48025-1-danielmaraboo@gmail.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 15253 bytes --]

Translate the code-of-conduct-interpretation.rst document from
Documentation/process/ to Portuguese (pt_BR) to make the kernel
guidelines on community standards and enforcement more accessible
to Portuguese-speaking developers.

Signed-off-by: Daniel Pereira <danielmaraboo@gmail.com>
---
 Documentation/translations/pt_BR/index.rst    |   1 +
 .../code-of-conduct-interpretation.rst        | 257 ++++++++++++++++++
 2 files changed, 258 insertions(+)
 create mode 100644 Documentation/translations/pt_BR/process/code-of-conduct-interpretation.rst

diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst
index 841b49657..d9276a8dc 100644
--- a/Documentation/translations/pt_BR/index.rst
+++ b/Documentation/translations/pt_BR/index.rst
@@ -84,3 +84,4 @@ kernel e sobre como ver seu trabalho integrado.
    Processo do subsistema KVM x86 <process/maintainer-kvm-x86>
    Adicionando uma nova chamada de Sistema <process/adding-syscalls>
    Lista de verificação para submissão de patches do kernel Linux <process/submit-checklist>
+   Interpretação do Código de Conduta do Kernel Linux <process/code-of-conduct-interpretation>
diff --git a/Documentation/translations/pt_BR/process/code-of-conduct-interpretation.rst b/Documentation/translations/pt_BR/process/code-of-conduct-interpretation.rst
new file mode 100644
index 000000000..866c9f7e7
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/code-of-conduct-interpretation.rst
@@ -0,0 +1,257 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Interpretação do Código de Conduta do Kernel Linux
+==================================================
+
+O :ref:`pt_BR_code_of_conduct` é um documento geral que tem como objetivo
+fornecer um conjunto de regras para quase todas as comunidades de código
+aberto. Toda comunidade de código aberto é única e o kernel Linux não é
+exceção. Por causa disso, este documento descreve como nós, na comunidade
+do kernel Linux, o interpretaremos. Nós também não esperamos que esta
+interpretação seja estática ao longo do tempo, e a ajustaremos conforme
+necessário.
+
+O esforço de desenvolvimento do kernel Linux é um processo muito pessoal
+em comparação com as formas "tradicionais" de desenvolvimento de software.
+Suas contribuições e as ideias por trás delas serão cuidadosamente
+revisadas, frequentemente resultando em críticas e apontamentos. A
+revisão quase sempre exigirá melhorias antes que o material possa ser
+incluído no kernel. Saiba que isso acontece porque todos os envolvidos
+querem ver a melhor solução possível para o sucesso geral do Linux. Este
+processo de desenvolvimento provou criar o kernel de sistema operacional
+mais robusto de todos os tempos, e nós não queremos fazer nada que cause
+a diminuição da qualidade do envio e do resultado final.
+
+Mantenedores
+------------
+
+O Código de Conduta usa o termo "mantenedores" várias vezes. Na
+comunidade do kernel, um "mantenedor" é qualquer pessoa responsável por
+um subsistema, driver ou arquivo, e que esteja listada no arquivo
+MAINTAINERS na árvore de código-fonte do kernel.
+
+Responsabilidades
+-----------------
+
+O Código de Conduta menciona direitos e responsabilidades para os
+mantenedores, e isso precisa de alguns esclarecimentos adicionais.
+
+Em primeiro lugar e acima de tudo, é uma expectativa razoável que os
+mantenedores liderem pelo exemplo.
+
+Dito isto, nossa comunidade é vasta e ampla, e não há um novo requisito
+para que os mantenedores lidem unilateralmente com o comportamento de
+outras pessoas nas partes da comunidade onde atuam. Essa responsabilidade
+é de todos nós e, em última análise, o Código de Conduta documenta os
+caminhos finais de escalonamento em caso de preocupações não resolvidas
+em relação a questões de conduta.
+
+Os mantenedores devem estar dispostos a ajudar quando ocorrerem problemas
+e trabalhar com outras pessoas na comunidade quando necessário. Não tenha
+medo de entrar em contato com o Conselho Consultivo Técnico (TAB) ou
+outros mantenedores se não tiver certeza de como lidar com as situações
+que surgirem. Isso não será considerado um relato de violação, a menos
+que você queira que seja. Se não tiver certeza sobre como abordar o TAB
+ou quaisquer outros mantenedores, entre em contato com nossa mediadora
+de conflitos, Joanna Lee <jlee@linuxfoundation.org>.
+
+No final, "sejam gentis uns com os outros" é realmente o objetivo final
+para todos. Sabemos que todos são humanos e que todos falhamos às vezes,
+mas o objetivo principal para todos nós deve ser trabalhar em direção a
+resoluções amigáveis dos problemas. A aplicação do código de conduta será
+apenas uma opção de último recurso.
+
+Nosso objetivo de criar um sistema operacional robusto e tecnicamente
+avançado e a complexidade técnica envolvida exigem naturalmente
+conhecimento técnico e tomada de decisões.
+
+O conhecimento técnico exigido varia dependendo da área de contribuição.
+Ele é determinado principalmente pelo contexto e pela complexidade técnica
+e apenas secundariamente pelas expectativas de contribuidores e
+mantenedores.
+
+Tanto as expectativas de conhecimento técnico quanto a tomada de decisões
+estão sujeitas a discussão, mas no final das contas há uma necessidade
+básica de sermos capazes de tomar decisões para progredir. Esta
+prerrogativa está nas mãos dos mantenedores e da liderança do projeto e
+espera-se que seja usada de boa fé.
+
+Como consequência, definir expectativas de conhecimento técnico, tomar
+decisões e rejeitar contribuições inadequadas não são vistos como uma
+violação do Código de Conduta.
+
+Embora os mantenedores sejam em geral receptivos aos novatos, sua
+capacidade de ajudar os contribuidores a superar os obstáculos de entrada
+é limitada, portanto, eles devem definir prioridades. Isso, também, não
+deve ser visto como uma violação do Código de Conduta. A comunidade do
+kernel está ciente disso e fornece programas de nível de entrada de
+várias formas, como o kernelnewbies.org.
+
+Escopo
+------
+
+A comunidade do kernel Linux interage primariamente em um conjunto de listas
+de e-mail públicas distribuídas por vários servidores diferentes controlados
+por várias empresas ou indivíduos diferentes. Todas essas listas estão
+definidas no arquivo MAINTAINERS na árvore de código-fonte do kernel.
+Quaisquer e-mails enviados para essas listas de e-mail são considerados
+cobertos pelo Código de Conduta.
+
+Desenvolvedores que usam o bugzilla do kernel.org e outras ferramentas de
+rastreamento de bugs ou bugzilla de subsistemas devem seguir as diretrizes
+do Código de Conduta. A comunidade do kernel Linux não possui um endereço
+de e-mail de projeto "oficial" ou endereço "oficial" de mídia social.
+Qualquer atividade realizada usando uma conta de e-mail do kernel.org deve
+seguir o Código de Conduta conforme publicado para o kernel.org, assim como
+qualquer indivíduo usando uma conta de e-mail corporativa deve seguir as
+regras específicas daquela corporação.
+
+O Código de Conduta não proíbe que se continue a incluir nomes, endereços de
+e-mail e comentários associados em mensagens de listas de discussão,
+mensagens de log de alterações (changelog) do kernel ou comentários no
+código.
+
+A interação em outros fóruns é coberta pelas regras que se aplicam a tais
+fóruns e, em geral, não é coberta pelo Código de Conduta. Exceções podem
+ser consideradas para circunstâncias extremas.
+
+As contribuições enviadas para o kernel devem usar linguagem apropriada.
+O conteúdo já existente que precede o Código de Conduta não será tratado
+agora como uma violação. No entanto, a linguagem inapropriada pode ser vista
+como um bug; tais bugs serão corrigidos mais rapidamente se quaisquer partes
+interessadas enviarem patches com esse propósito. Expressões que atualmente
+fazem parte da API de usuário/kernel, ou que refletem a terminologia usada
+em padrões ou especificações publicadas, não são consideradas bugs.
+
+Aplicação
+---------
+
+O endereço listado no Código de Conduta vai para o Comitê do Código de
+Conduta. Os membros exatos que recebem esses e-mails a qualquer momento
+estão listados em https://kernel.org/code-of-conduct.html. Os membros não
+podem acessar relatos feitos antes de se juntarem ou após terem deixado o
+comitê.
+
+O Comitê do Código de Conduta consiste em membros voluntários da comunidade
+nomeados pelo TAB, bem como um mediador profissional agindo como um terceiro
+neutro. Os processos que o comitê do Código de Conduta usará para lidar com
+os relatos variam e dependerão das circunstâncias individuais; no entanto,
+este arquivo serve como documentação para o processo geral utilizado.
+
+Qualquer membro do comitê, incluindo o mediador, pode ser contatado
+diretamente se o relator não desejar incluir todo o comitê em uma
+reclamação ou preocupação.
+
+O Comitê do Código de Conduta revisa os casos de acordo com os processos
+(veja acima) e consulta o TAB conforme a necessidade e a conveniência,
+por exemplo, para solicitar e receber informações sobre a comunidade do
+kernel.
+
+Quaisquer decisões a respeito de recomendações de aplicação (enforcement)
+serão levadas ao TAB para implementação junto aos mantenedores relevantes,
+se necessário. Uma vez que o TAB aprove uma ou mais das medidas descritas
+no escopo do banimento pelo voto de dois terços dos membros, o Comitê do
+Código de Conduta aplicará as medidas aprovadas pelo TAB. Quaisquer membros
+do Comitê do Código de Conduta que sirvam no TAB não votarão nas medidas.
+
+Em intervalos trimestrais, o Comitê do Código de Conduta e o TAB fornecerão
+um relatório resumindo os relatos anonimizados que o comitê do Código de
+Conduta recebeu e o status deles, bem como os detalhes de quaisquer
+decisões aprovadas pelo TAB, incluindo dados completos e identificáveis da
+votação.
+
+Como a maneira pela qual interpretamos e aplicamos o Código de Conduta
+evoluirá com o tempo, este documento será atualizado quando necessário para
+refletir quaisquer mudanças.
+
+Aplicação para Violações de Comportamento Inaceitável do Código de Conduta
+----------------------------------------------------------------------------
+
+O comitê do Código de Conduta trabalha para garantir que nossa comunidade
+continue a ser inclusiva e promova discussões e pontos de vista diversos, e
+trabalha para melhorar essas características ao longo do tempo. A maioria
+dos relatos que o Comitê do Código de Conduta recebe decorre da
+compreensão incorreta sobre o processo de desenvolvimento e os papéis,
+responsabilidades e o direito dos mantenedores de tomar decisões sobre a
+aceitação de código. Estes são resolvidos através do esclarecimento do
+processo de desenvolvimento e do escopo do Código de Conduta.
+
+Comportamentos inaceitáveis podem interromper a colaboração respeitosa por um
+curto período de tempo e impactar negativamente a saúde da comunidade a longo
+prazo. Comportamentos inaceitáveis frequentemente são resolvidos quando os
+indivíduos reconhecem seu comportamento e se retratam por ele no ambiente em
+que a violação ocorreu.
+
+O Comitê do Código de Conduta recebe relatos sobre comportamentos
+inaceitáveis quando eles não são resolvidos através de discussões na
+comunidade. O comitê do Código de Conduta toma medidas para restaurar a
+colaboração produtiva e respeitosa quando um comportamento inaceitável
+impactou negativamente esse relacionamento.
+
+O Comitê do Código de Conduta tem a obrigação de manter os relatos e as
+informações dos relatores em sigilo. Os relatos podem vir de partes lesadas
+e membros da comunidade que são observadores de comportamentos
+inaceitáveis. O Comitê do Código de Conduta tem a responsabilidade de
+investigar e resolver esses relatos, trabalhando com todas as partes
+envolvidas.
+
+O Comitê do Código de Conduta trabalha com o indivíduo para promover uma
+mudança em sua compreensão sobre a importância de reparar os danos causados
+por seu comportamento à parte lesada e o impacto negativo a longo prazo na
+comunidade.
+
+O objetivo é alcançar uma resolução que seja aceitável para todas as partes.
+Se trabalhar com o indivíduo não trouxer o resultado desejado, o Comitê do
+Código de Conduta avaliará outras medidas, como buscar um pedido de
+desculpas público para reparar o dano.
+
+Buscar retratação pública pela violação
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+O Comitê do Código de Conduta chama a atenção publicamente para o comportamento
+no ambiente em que a violação ocorreu, buscando uma retratação pública
+pela violação.
+
+Uma retratação pública pela violação é o primeiro passo para reconstruir a
+confiança. A confiança é essencial para o sucesso contínuo e a saúde da
+comunidade, que opera com base na confiança e no respeito.
+
+Medidas corretivas se não houver uma retratação pública pela violação
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+O Comitê do Código de Conduta determina o próximo curso de ação para restaurar
+a colaboração saudável, recomendando medida(s) corretiva(s) ao TAB para
+aprovação.
+
+- Banir o infrator de participar do processo de desenvolvimento do kernel por
+  um período de até um ciclo completo de desenvolvimento do kernel. O Comitê
+  do Código de Conduta pode exigir uma retratação pública como condição
+  para suspender o banimento.
+
+O escopo do banimento por um período de tempo pode incluir:
+
+    a. negar contribuições de patch e pull requests
+    b. pausar a colaboração com o infrator ignorando suas contribuições e/ou
+       bloqueando sua(s) conta(s) de e-mail
+    c. restringir sua capacidade de se comunicar pelas plataformas kernel.org,
+       como listas de discussão e sites de mídia social
+
+Uma vez que o TAB aprove uma ou mais das medidas descritas no escopo do
+banimento por dois terços dos membros votando a favor das medidas, o Comitê do
+Código de Conduta aplicará a(s) medida(s) aprovada(s) pelo TAB em colaboração
+com a comunidade, mantenedores, submantenedores e administradores do
+kernel.org. Quaisquer membros do Comitê do Código de Conduta atuando no TAB
+não votarão nas medidas.
+
+O Comitê do Código de Conduta está ciente do impacto negativo que buscar uma
+retratação pública e instituir um banimento pode ter sobre os indivíduos.
+Também está ciente dos danos a longo prazo para a comunidade que podem resultar
+da falta de ação quando tais violações públicas graves ocorrem.
+
+A eficácia da(s) medida(s) corretiva(s) aprovada(s) pelo TAB depende da
+confiança e cooperação da comunidade, mantenedores, submantenedores e
+administradores do kernel.org na sua aplicação.
+
+O Comitê do Código de Conduta espera sinceramente que comportamentos
+inaceitáveis que exijam a busca de retratações públicas continuem a ser
+ocorrências extremamente raras no futuro.
\ No newline at end of file
-- 
2.47.3


^ permalink raw reply related

* [PATCH 1/4] docs: pt_BR: Translate submit-checklist to Portuguese
From: Daniel Pereira @ 2026-07-16  2:10 UTC (permalink / raw)
  To: corbet; +Cc: linux-doc, Daniel Pereira
In-Reply-To: <20260716021013.48025-1-danielmaraboo@gmail.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 7979 bytes --]

Translate the submit-checklist document from Documentation/process/
to Portuguese (pt_BR) to make the kernel contribution guidelines
more accessible to Portuguese-speaking developers.

Also, add the newly translated file to the main index in the pt_BR
translation directory to ensure it compiles and links correctly
within the Sphinx build.

Signed-off-by: Daniel Pereira <danielmaraboo@gmail.com>
---
 Documentation/translations/pt_BR/index.rst    |   1 +
 .../pt_BR/process/submit-checklist.rst        | 145 ++++++++++++++++++
 2 files changed, 146 insertions(+)
 create mode 100644 Documentation/translations/pt_BR/process/submit-checklist.rst

diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst
index 2ab14c5d6..841b49657 100644
--- a/Documentation/translations/pt_BR/index.rst
+++ b/Documentation/translations/pt_BR/index.rst
@@ -83,3 +83,4 @@ kernel e sobre como ver seu trabalho integrado.
    Conformidade de DTS para SoC <process/maintainer-soc-clean-dts>
    Processo do subsistema KVM x86 <process/maintainer-kvm-x86>
    Adicionando uma nova chamada de Sistema <process/adding-syscalls>
+   Lista de verificação para submissão de patches do kernel Linux <process/submit-checklist>
diff --git a/Documentation/translations/pt_BR/process/submit-checklist.rst b/Documentation/translations/pt_BR/process/submit-checklist.rst
new file mode 100644
index 000000000..003fc9568
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/submit-checklist.rst
@@ -0,0 +1,145 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============================================================
+Lista de verificação para submissão de patches do kernel Linux
+==============================================================
+
+Aqui estão algumas coisas básicas que os desenvolvedores devem fazer se
+quiserem ver suas submissões de patches de kernel aceitas mais rapidamente.
+
+Estas diretrizes vão além da documentação fornecida em
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+e em outros locais sobre o envio de patches para o kernel Linux.
+
+Revise seu código
+=================
+
+1) Se você usar um recurso, faça o #include do arquivo que define/declara
+   esse recurso. Não dependa de outros arquivos de cabeçalho que incluam
+   os que você usa de forma indireta.
+
+2) Verifique o estilo geral do seu patch conforme detalhado em
+   :ref:`Documentation//process/coding-style.rst <codingstyle>`.
+
+3) Todas as barreiras de memória {por exemplo, ``barrier()``, ``rmb()``,
+   ``wmb()``} precisam de um comentário no código-fonte que explique a
+   lógica do que estão fazendo e o porquê.
+
+Revise as alterações do Kconfig
+===============================
+
+1) Quaisquer novas ou modificadas opções de ``CONFIG`` não bagunçam o
+   menu de configuração e têm 'desativado' (off) como padrão, a menos que
+   atendam aos critérios de exceção documentados em
+   ``Documentation/kbuild/kconfig-language.rst``, atributos de menu: valor
+   padrão.
+
+2) Todas as novas opções de ``Kconfig`` possuem texto de ajuda.
+
+3) Foram cuidadosamente revisadas com relação às combinações relevantes de
+   ``Kconfig``. Isso é muito difícil de acertar apenas com testes --- exige
+   capacidade de raciocínio.
+   pays off here.
+
+Forneça documentação
+====================
+
+1) Inclua :ref:`kernel-doc <kernel_doc>` para documentar as APIs globais
+   do kernel. (Não é obrigatório para funções estáticas, mas também é
+   aceitável nelas.)
+
+2) Todas as novas entradas em ``/proc`` devem ser documentadas sob
+   ``Documentation/``.
+
+3) Todos os novos parâmetros de inicialização (boot) do kernel devem ser
+   documentados em ``Documentation/admin-guide/kernel-parameters.rst``.
+
+4) Todos os novos parâmetros de módulo devem ser documentados com
+   ``MODULE_PARM_DESC()``.
+
+5) Todas as novas interfaces com o espaço de usuário (userspace) devem ser
+   documentadas em ``Documentation/ABI/``. Consulte
+   ``Documentation/admin-guide/abi.rst`` (ou ``Documentation/ABI/README``)
+   para obter mais informações. Patches que alteram interfaces de espaço
+   de usuário devem incluir em cópia (CC) linux-api@vger.kernel.org.
+
+6) Se quaisquer ioctls forem adicionados pelo patch, atualize também
+   ``Documentation/userspace-api/ioctl/ioctl-number.rst``.
+
+Verifique seu código com ferramentas
+====================================
+
+1) Verifique se há violações triviais com o verificador de estilo de patch
+   antes do envio (``scripts/checkpatch.pl``). Você deve ser capaz de
+   justificar todas as violações que permanecerem no seu patch.
+
+2) Faça uma verificação limpa com o sparse.
+
+3) Use ``make checkstack`` e corrija quaisquer problemas encontrados por ele.
+   Observe que o ``checkstack`` não aponta problemas explicitamente, mas
+   qualquer função individual que utilize mais de 512 bytes na pilha é uma
+   candidata a alteração.
+
+Compile seu código
+==================
+
+1) Compila de forma limpa:
+
+  a) com as opções de ``CONFIG`` aplicáveis ou modificadas definidas como
+     ``=y``, ``=m`` e ``=n``. Sem avisos/erros do ``gcc``, sem avisos/erros do
+     vinculador (linker).
+
+  b) Passa em ``allnoconfig``, ``allmodconfig``
+
+  c) Compila com sucesso ao usar ``O=builddir``
+
+  d) Quaisquer alterações em Documentation/ compilam com sucesso sem novos
+     avisos/erros. Use ``make htmldocs`` ou ``make pdfdocs`` para verificar
+     a compilação e corrigir quaisquer problemas.
+
+2) Compila em múltiplas arquiteturas de CPU usando ferramentas locais de
+   compilação cruzada (cross-compile) ou alguma outra fazenda de compilação
+   (build farm).
+   Observe que testar em arquiteturas de diferentes tamanhos de palavra
+   (32 e 64 bits) e diferentes endianness (big- e little-endian) é eficaz
+   para capturar vários problemas de portabilidade decorrentes de falsas
+   suposições sobre o intervalo de quantidade representável, alinhamento
+   de dados ou endianness, entre outros.
+
+3) O novo código adicionado foi compilado com ``gcc -W`` (use
+   ``make KCFLAGS=-W``). Isso gerará muito ruído, mas é bom para encontrar
+   bugs como "warning: comparison between signed and unsigned".
+
+4) Se o seu código-fonte modificado depender ou usar quaisquer APIs ou
+   recursos do kernel relacionados aos seguintes símbolos do ``Kconfig``,
+   teste múltiplas compilações com os símbolos relacionados do ``Kconfig``
+   desativados e/ou definidos como ``=m`` (se essa opção estiver disponível)
+   [não todos ao mesmo tempo, apenas combinações variadas/aleatórias deles]:
+
+   ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``,
+   ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+   ``CONFIG_NET``, ``CONFIG_INET=n`` (mas este último com ``CONFIG_NET=y``).
+
+Teste seu código
+================
+
+1) Foi testado com ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+   ``CONFIG_SLUB_DEBUG``, ``CONFIG_DEBUG_PAGEALLOC``,
+   ``CONFIG_DEBUG_MUTEXES``, ``CONFIG_DEBUG_SPINLOCK``,
+   ``CONFIG_DEBUG_ATOMIC_SLEEP``, ``CONFIG_PROVE_RCU`` e
+   ``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` todos habilitados simultaneamente.
+
+2) Foi testado em tempo de compilação e de execução com e sem ``CONFIG_SMP``
+   e ``CONFIG_PREEMPT``.
+
+3) Todos os caminhos de código foram executados com todos os recursos de
+   lockdep ativados.
+
+4) Foi verificado com a injeção de falhas de pelo menos slab e alocação de
+   páginas. Consulte ``Documentation/fault-injection/``.
+   Se o novo código for substancial, a adição de injeção de falhas específica
+   do subsistema pode ser apropriada.
+
+5) Testado com a tag mais recente do linux-next para garantir que ele ainda
+   funcione com todos os outros patches enfileirados e com várias alterações
+   na VM, VFS e outros subsistemas.
-- 
2.47.3


^ permalink raw reply related

* (no subject)
From: Daniel Pereira @ 2026-07-16  2:10 UTC (permalink / raw)
  To: corbet; +Cc: linux-doc, Daniel Pereira

Subject: [PATCH 0/4] doc: pt_BR: Add translations for process and guidelines

Hello,

This patch series adds the Brazilian Portuguese (pt_BR) translations for
several essential files regarding community standards, submit checklists, and
best development practices. 

Specifically, this series translates:
1. The submit-checklist guide.
2. The Code of Conduct interpretation document.
3. The core Contributor Covenant Code of Conduct.
4. The deprecated interfaces, attributes, and language features guide.

All files have been formatted to respect the 80-character line limit and
the main index.rst has been updated accordingly. The Sphinx documentation build 
(make htmldocs) compiles successfully with no warnings or errors related to 
these new files.

Thanks!

Daniel Pereira (4):
  docs: pt_BR: Translate submit-checklist to Portuguese
  docs: pt_BR: Translate code-of-conduct-interpretation to Portuguese
  docs: pt_BR: Translate Code of Conduct to Portuguese
  docs: pt_BR: Translate deprecated interfaces guide to Portuguese

 Documentation/translations/pt_BR/index.rst    |   5 +
 .../code-of-conduct-interpretation.rst        | 257 +++++++++++
 .../pt_BR/process/code-of-conduct.rst         |  88 ++++
 .../translations/pt_BR/process/deprecated.rst | 422 ++++++++++++++++++
 .../pt_BR/process/submit-checklist.rst        | 145 ++++++
 5 files changed, 917 insertions(+)
 create mode 100644 Documentation/translations/pt_BR/process/code-of-conduct-interpretation.rst
 create mode 100644 Documentation/translations/pt_BR/process/code-of-conduct.rst
 create mode 100644 Documentation/translations/pt_BR/process/deprecated.rst
 create mode 100644 Documentation/translations/pt_BR/process/submit-checklist.rst

-- 
2.47.3


^ permalink raw reply

* Re: [PATCH net v3] tun/tap & vhost-net: make qdisc backpressure opt-in via IFF_BACKPRESSURE
From: Oliver Sang @ 2026-07-16  1:22 UTC (permalink / raw)
  To: Simon Schippers
  Cc: oe-lkp, lkp, Brett Sheffield, netdev, linux-kernel, ltp,
	Willem de Bruijn, Jason Wang, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Michael S . Tsirkin, Simon Horman,
	Jonathan Corbet, Shuah Khan, Andrew Lunn, Tim Gebauer, linux-doc,
	oliver.sang
In-Reply-To: <1ecf0eb8-17ef-4f9c-ba87-da69d207e4d4@tu-dortmund.de>

hi, Simon Schippers,

On Wed, Jul 15, 2026 at 04:32:26PM +0200, Simon Schippers wrote:
> On 7/15/26 16:01, kernel test robot wrote:
> > 
> > 
> > Hello,
> > 
> > kernel test robot noticed "ltp.ioctl03.fail" on:
> 
> ioctl03.c does not know about IFF_BACKPRESSURE which is introduced here,
> consequently it fails.
> See [1] where it compares TUN features with known_flags.

thanks a lot for information!

> 
> Thanks.
> 
> [1] Link: https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/syscalls/ioctl/ioctl03.c#L82
> 

[...]

^ permalink raw reply

* Re: [PATCH v7 05/10] tracing: wprobe: Use a new seq_print_ip_sym_offset() wrapper
From: Masami Hiramatsu @ 2026-07-16  0:24 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Steven Rostedt, Peter Zijlstra, Ingo Molnar, x86, Jinchao Wang,
	Mathieu Desnoyers, Thomas Gleixner, Borislav Petkov, Dave Hansen,
	H . Peter Anvin, Alexander Shishkin, Ian Rogers, linux-kernel,
	linux-trace-kernel, linux-doc, linux-perf-users
In-Reply-To: <178407989708.95826.17630423823637072384.stgit@devnote2>

Oops, I missed to fold this in the 1st patch...
(the seq_print_ip_sym_offset() part is already folded)

Thanks,

On Wed, 15 Jul 2026 10:44:57 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> 
> Use a new seq_print_ip_sym_offset() wrapper function instead of
> using TRACE_ITER(SYM_OFFSET) mask directly.
> 
> Link: https://lore.kernel.org/all/176226550596.59499.18020648957674458755.stgit@devnote2/
> 
> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> ---
>  kernel/trace/trace_wprobe.c |    1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/kernel/trace/trace_wprobe.c b/kernel/trace/trace_wprobe.c
> index b52f3eac719f..dd310a87b333 100644
> --- a/kernel/trace/trace_wprobe.c
> +++ b/kernel/trace/trace_wprobe.c
> @@ -20,6 +20,7 @@
>  #include <asm/ptrace.h>
>  
>  #include "trace_dynevent.h"
> +#include "trace_output.h"
>  #include "trace_probe.h"
>  #include "trace_probe_kernel.h"
>  #include "trace_probe_tmpl.h"
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* Re: [PATCH bpf-next v5 1/8] netlink: specs: add XDP RX checksum capability to XDP metadata specs
From: bot+bpf-ci @ 2026-07-15 22:24 UTC (permalink / raw)
  To: lorenzo, donald.hunter, kuba, davem, edumazet, pabeni, horms, ast,
	daniel, hawk, john.fastabend, sdf, andrew+netdev,
	anthony.l.nguyen, przemyslaw.kitszel, aleksander.lobakin, andrii,
	martin.lau, eddyz87, song, yonghong.song, kpsingh, haoluo, jolsa,
	shuah, maciej.fijalkowski, corbet, skhan, memxor, emil
  Cc: deliran, jakub, netdev, bpf, intel-wired-lan, linux-kselftest,
	linux-doc, aleksandr.loktionov, lorenzo, ast, andrii, daniel,
	martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-1-623d5c0d0ab7@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 2470 bytes --]

> diff --git a/net/core/xdp.c b/net/core/xdp.c
> index 9890a30584ba..9bcaa423ad17 100644
> --- a/net/core/xdp.c
> +++ b/net/core/xdp.c
> @@ -961,6 +961,38 @@ __bpf_kfunc int bpf_xdp_metadata_rx_vlan_tag(const struct xdp_md *ctx,
>  	return -EOPNOTSUPP;
>  }
>
> +/**
> + * bpf_xdp_metadata_rx_checksum - Read XDP frame RX checksum.
> + * @ctx: XDP context pointer.
> + * @ip_summed: Return value pointer to a bitmask indicating available checksums.
> + * @cksum: Return value pointer indicating the hw checksum value.
> + * @cksum_level: Return value pointer indicating the checksum level result.
> + *
> + * In case of success, ``ip_summed`` is set to the RX checksum result. Possible
> + * values are:
> + * ``XDP_CHECKSUM_NONE``
> + * ``XDP_CHECKSUM_UNNECESSARY``
> + * ``XDP_CHECKSUM_COMPLETE``
> + * ``XDP_CHECKSUM_COMPLETE`` | ``XDP_CHECKSUM_UNNECESSARY``
> + *
> + * In case of success, ``cksum`` contains the checksum value calculated by the
> + * NIC. ``cksum`` is valid only if ``XDP_CHECKSUM_COMPLETE`` is set in
> + * ``ip_summed``. ``cksum_level`` contains the checksum level reported by the
> + * hw. ``cksum_level`` can be considered valid only if
> + * ``XDP_CHECKSUM_UNNECESSARY`` is set in ``ip_summed``.

Earlier review of this series raised the case where the NIC reports
COMPLETE or UNNECESSARY, the XDP program then modifies the packet and
returns XDP_PASS.  In that situation the reported checksum is stale.

It was noted on the list that drivers today do not invalidate the
checksum in this case, they only stop reporting COMPLETE while an XDP
program is attached.

Would it help to document that expected driver behavior here (how it
works today versus what is expected), and possibly add a kselftest that
checks it?  If this is handled in a later patch of the series, please
disregard.

> + *
> + * Return:
> + * * Returns 0 on success or ``-errno`` on error.
> + * * ``-EOPNOTSUPP`` : means device driver does not implement kfunc
> + * * ``-ENODATA``    : means no RX-checksum available for this frame
> + */
> +__bpf_kfunc int bpf_xdp_metadata_rx_checksum(const struct xdp_md *ctx,
> +					     enum xdp_checksum *ip_summed,
> +					     u32 *cksum, u8 *cksum_level)
> +{
> +	return -EOPNOTSUPP;
> +}


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/29453967825

^ permalink raw reply

* Re: [PATCH v6 5/5] iio: dac: Add AD5529R DAC driver support
From: Uwe Kleine-König @ 2026-07-15 22:22 UTC (permalink / raw)
  To: Janani Sunil
  Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
	David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, Jonathan Corbet,
	Shuah Khan, Mark Brown, Marius Cristea, Marcus Folkesson,
	Kent Gustavsson, linux-iio, devicetree, linux-kernel, linux-doc,
	Janani Sunil, linux-spi, Kent Gustavsson
In-Reply-To: <20260715-ad5529r-driver-v6-5-cfdf8b9f5ee3@analog.com>

[-- Attachment #1: Type: text/plain, Size: 772 bytes --]

Hello,

On Wed, Jul 15, 2026 at 01:41:08PM +0200, Janani Sunil wrote:
> +#include <linux/array_size.h>
> +#include <linux/bits.h>
> +#include <linux/delay.h>
> +#include <linux/dev_printk.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/iio/iio.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/property.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +#include <linux/spi/spi.h>
> +#include <linux/types.h>
> +#include <linux/units.h>

Please don't add new usages of <linux/mod_devicetable.h>, both
of_device_id and spi_device_id are provided by <linux/spi/spi.h>, so the
#include for <linux/mod_devicetable.h> can just be dropped.

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v27 3/7] firmware: imx: add driver for NXP EdgeLock Enclave
From: Uwe Kleine-König @ 2026-07-15 22:19 UTC (permalink / raw)
  To: pankaj.gupta
  Cc: Jonathan Corbet, Shuah Khan, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Pankaj Gupta, linux-doc, linux-kernel, devicetree,
	imx, linux-arm-kernel, Frieder Schrempf, sashiko-bot
In-Reply-To: <20260715-imx-se-if-v27-3-bb7c45952f06@nxp.com>

[-- Attachment #1: Type: text/plain, Size: 37988 bytes --]

Hello,

On Wed, Jul 15, 2026 at 11:39:09PM +0530, pankaj.gupta@oss.nxp.com wrote:
> From: Pankaj Gupta <pankaj.gupta@nxp.com>
> 
> Add MU-based communication interface for secure enclave.
> 
> NXP hardware IP(s) for secure-enclaves like Edgelock Enclave(ELE), are
> embedded in the SoC to support the features like HSM, SHE & V2X, using
> message based communication interface.
> 
> The secure enclave FW communicates with Linux over single or multiple
> dedicated messaging unit(MU) based interface(s).
> Exists on i.MX SoC(s) like i.MX8ULP, i.MX93, i.MX95 etc.
> 
> For i.MX9x SoC(s) there is at least one dedicated ELE MU(s) for each
> world - Linux(one or more) and OPTEE-OS (one or more).
> 
> Other dependent kernel drivers will be:
> - NVMEM: that supports non-volatile devices like EFUSES,
>   managed by NXP's secure-enclave.
> 
> Signed-off-by: Pankaj Gupta <pankaj.gupta@nxp.com>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Tested-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> ---
> Changes from v26 to v27
> 
> Fix several issues reported by Sashiko in the ELE driver:
> --------------------------------------------------------
> 
> 1. Critical: encrypted IMEM DMA/physical address discarded / address 0
>    Status: Fixed.
>    The IMEM buffer now uses dma_addr_t daddr, and save/restore paths
>    pass imem->daddr to ele_service_swap(). This resolves the old issue
>    where imem.phyaddr could remain zero.
> 
> 2. High: ele_msg_send() failure leaves waiting_rsp_clbk_hdl.rx_msg dangling
>    Status: Fixed.
>    ele_msg_send_rcv() now uses a common clear_waiter path. On ele_msg_send()
>    failure, the response waiter state is cleared under
>    waiting_rsp_clbk_hdl.clbk_rx_lock.
> 
> 3. High: tx_msg may be freed while mailbox still has async pointer
>    Status: Addressed
>    The i.MX MU mailbox controller copies the message payload into
>    hardware registers synchronously in imx_mu_send_data(). The ELE
>    client does not retain the tx_msg buffer after mbox_send_message()
>    returns, and TX completion is handled by the mailbox controller/core
>    "knows_txdone" set as false.
> 
> 4. High: global var_se_info shared mutable state
>    Status: Fixed.
>    Mutable firmware-load and IMEM state is now per-device in struct
>    se_if_priv. get_load_fw_instance() returns &priv->load_fw. The
>    remaining var_se_info only carries common SoC-level revision data.
> 
> 5. High: ele_service_swap() silently truncates 64-bit address
>    Status: Fixed.
>    ele_service_swap() now takes dma_addr_t, and the v27 changelog
>    states that upper 32-bit addresses are rejected before placing
>    the low 32 bits into the ELE message field.
>    Firmware authentication and IMEM service-swap paths use DMA
>    addresses end-to-end.
> 
> 6. High: soc_device_register() handle not unregistered
>    Status: Fixed.
>    The code now registers a devres action using devm_add_action_or_reset()
>    to call soc_device_unregister() for the soc_device_register() result.
> 
> 7. High: manual dmam_free_coherent() can double-free devres memory
>    Status: Fixed.
>    The explicit dmam_free_coherent() for the encrypted IMEM buffer
>    is removed from probe cleanup. The buffer is now treated as
>    devres-managed and released by devres.
> 
> 8. High: hardcoded MAX_SCHEDULE_TIMEOUT bypasses response timeout
>    Status: Fixed / design-controlled.
>    The response-wait path now uses callback-handle identity to decide
>    whether timeout applies, instead of using command-receiver file
>    identity. Command receiver daemon wait remains intentionally
>    long/indefinite by design. The miscdev patch also shows timeout
>    handling moved toward per-dev_ctx context.
> 
> 9. Medium: ele_get_info() mixes goto cleanup with __free()
>    Status: Not Accepted.
>    This was intentionally not changed. The scoped __free(kfree) ownership
>    for tx_msg/rx_msg and the manual gen_pool/DMA cleanup for get_info_data
>    are separate ownership domains.
> 
> 10. Medium: lockless clearing of rx_msg
>     Status: Fixed.
>     The response callback state is now cleared under
>     waiting_rsp_clbk_hdl.clbk_rx_lock in the common cleanup path.
> 
> 11. Low: resume ignores se_restore_imem_state() return value
>     Status: Fixed with non-fatal PM policy.
>     The return value is now captured and logged. The driver intentionally
>     keeps suspend/resume non-fatal if IMEM save/restore fails.
> 
> Reported-by: sashiko-bot <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/patchset/20260629-imx-se-if-v26-0-146446285744@nxp.com?part=3
> 
> 12. Address review feedback from Lothar Waßmann.
> 
>     Make se_fill_cmd_msg_hdr() return void and remove dead error checks at its
>     call sites, since the helper only fills the message header and always
>     succeeded.
> 
>     Remove the trailing comma after the final empty of_device_id sentinel entry
>     so future compatible entries cannot accidentally be added after the table
>     terminator.
> ---
>  drivers/firmware/imx/Kconfig        |  13 ++
>  drivers/firmware/imx/Makefile       |   2 +
>  drivers/firmware/imx/ele_base_msg.c | 272 ++++++++++++++++++++++
>  drivers/firmware/imx/ele_base_msg.h |  98 ++++++++
>  drivers/firmware/imx/ele_common.c   | 448 ++++++++++++++++++++++++++++++++++++
>  drivers/firmware/imx/ele_common.h   |  43 ++++
>  drivers/firmware/imx/se_ctrl.c      | 410 +++++++++++++++++++++++++++++++++
>  drivers/firmware/imx/se_ctrl.h      | 111 +++++++++
>  include/linux/firmware/imx/se_api.h |  14 ++
>  9 files changed, 1411 insertions(+)
> 
> diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
> index 127ad752acf8..e3cb7f965e70 100644
> --- a/drivers/firmware/imx/Kconfig
> +++ b/drivers/firmware/imx/Kconfig
> @@ -55,3 +55,16 @@ config IMX_SCMI_MISC_DRV
>  	  core that could provide misc functions such as board control.
>  
>  	  This driver can also be built as a module.
> +
> +config IMX_SEC_ENCLAVE
> +	tristate "i.MX Embedded Secure Enclave - EdgeLock Enclave Firmware driver."
> +	depends on MAILBOX && ((IMX_MBOX && ARCH_MXC && ARM64) || COMPILE_TEST)
> +	select FW_LOADER
> +	default m if ARCH_MXC
> +
> +	help
> +	  Exposes APIs supported by the iMX Secure Enclave HW IP called:
> +	  - EdgeLock Enclave Firmware (for i.MX8ULP, i.MX93),
> +	    like base, HSM, V2X & SHE using the SAB protocol via the shared Messaging
> +	    Unit. This driver exposes these interfaces via a set of file descriptors
> +	    allowing to configure shared memory, send and receive messages.
> diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
> index 3bbaffa6e347..4412b15846b1 100644
> --- a/drivers/firmware/imx/Makefile
> +++ b/drivers/firmware/imx/Makefile
> @@ -4,3 +4,5 @@ obj-$(CONFIG_IMX_SCU)		+= imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o
>  obj-${CONFIG_IMX_SCMI_CPU_DRV}	+= sm-cpu.o
>  obj-${CONFIG_IMX_SCMI_MISC_DRV}	+= sm-misc.o
>  obj-${CONFIG_IMX_SCMI_LMM_DRV}	+= sm-lmm.o
> +sec_enclave-objs		= se_ctrl.o ele_common.o ele_base_msg.o
> +obj-${CONFIG_IMX_SEC_ENCLAVE}	+= sec_enclave.o
> diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c
> new file mode 100644
> index 000000000000..997854e10e14
> --- /dev/null
> +++ b/drivers/firmware/imx/ele_base_msg.c
> @@ -0,0 +1,272 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#include <linux/types.h>
> +
> +#include <linux/cleanup.h>
> +#include <linux/completion.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/genalloc.h>
> +
> +#include "ele_base_msg.h"
> +#include "ele_common.h"
> +
> +#define FW_DBG_DUMP_FIXED_STR		"ELE"
> +
> +int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info)
> +{
> +	dma_addr_t get_info_addr = 0;
> +	u32 *get_info_data = NULL;
> +	int ret = 0;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	memset(s_info, 0x0, sizeof(*s_info));
> +
> +	struct se_api_msg *tx_msg __free(kfree) =
> +		kzalloc(ELE_GET_INFO_REQ_MSG_SZ, GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	struct se_api_msg *rx_msg __free(kfree) =
> +		kzalloc(ELE_GET_INFO_RSP_MSG_SZ, GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	if (priv->mem_pool)
> +		get_info_data = gen_pool_dma_alloc(priv->mem_pool,
> +						   ELE_GET_INFO_BUFF_SZ,
> +						   &get_info_addr);
> +	else
> +		get_info_data = dma_alloc_coherent(priv->dev,
> +						   ELE_GET_INFO_BUFF_SZ,
> +						   &get_info_addr,
> +						   GFP_KERNEL);
> +	if (!get_info_data) {
> +		dev_err(priv->dev,
> +			"%s: Failed to allocate get_info_addr.", __func__);
> +		return -ENOMEM;
> +	}
> +
> +	se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
> +			    ELE_GET_INFO_REQ, ELE_GET_INFO_REQ_MSG_SZ, true);
> +
> +	tx_msg->data[0] = upper_32_bits(get_info_addr);
> +	tx_msg->data[1] = lower_32_bits(get_info_addr);
> +	tx_msg->data[2] = sizeof(*s_info);
> +	ret = ele_msg_send_rcv(priv, tx_msg, ELE_GET_INFO_REQ_MSG_SZ, rx_msg,
> +			       ELE_GET_INFO_RSP_MSG_SZ);
> +	if (ret < 0)
> +		goto exit;
> +
> +	ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_GET_INFO_REQ,
> +				      ELE_GET_INFO_RSP_MSG_SZ, true);
> +	if (ret < 0)
> +		goto exit;
> +
> +	memcpy(s_info, get_info_data, sizeof(*s_info));
> +exit:
> +	if (priv->mem_pool)
> +		gen_pool_free(priv->mem_pool, (unsigned long)get_info_data,
> +			      ELE_GET_INFO_BUFF_SZ);
> +	else
> +		dma_free_coherent(priv->dev, ELE_GET_INFO_BUFF_SZ,
> +				  get_info_data, get_info_addr);
> +
> +	return ret;
> +}
> +
> +int ele_fetch_soc_info(struct se_if_priv *priv, void *data)
> +{
> +	return ele_get_info(priv, data);
> +}
> +
> +int ele_ping(struct se_if_priv *priv)
> +{
> +	int ret = 0;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	struct se_api_msg *tx_msg __free(kfree) = kzalloc(ELE_PING_REQ_SZ,
> +							  GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	struct se_api_msg *rx_msg __free(kfree) = kzalloc(ELE_PING_RSP_SZ,
> +							  GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
> +			    ELE_PING_REQ, ELE_PING_REQ_SZ, true);
> +
> +	ret = ele_msg_send_rcv(priv, tx_msg, ELE_PING_REQ_SZ, rx_msg,
> +			       ELE_PING_RSP_SZ);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_PING_REQ,
> +				      ELE_PING_RSP_SZ, true);
> +
> +	return ret;
> +}
> +
> +int ele_service_swap(struct se_if_priv *priv,
> +		     dma_addr_t addr,
> +		     u32 addr_size, u16 flag)
> +{
> +	int ret = 0;
> +
> +	if (upper_32_bits(addr)) {
> +		dev_err(priv->dev,
> +			"ELE service-swap address exceeds 32-bit range: %pad\n",
> +			&addr);
> +		return -ERANGE;
> +	}
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	struct se_api_msg *tx_msg __free(kfree)	=
> +		kzalloc(ELE_SERVICE_SWAP_REQ_MSG_SZ, GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	struct se_api_msg *rx_msg __free(kfree) =
> +		kzalloc(ELE_SERVICE_SWAP_RSP_MSG_SZ, GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
> +			    ELE_SERVICE_SWAP_REQ, ELE_SERVICE_SWAP_REQ_MSG_SZ, true);
> +	if (ret)
> +		return ret;
> +
> +	tx_msg->data[0] = flag;
> +	tx_msg->data[1] = addr_size;
> +	tx_msg->data[2] = ELE_NONE_VAL;
> +	tx_msg->data[3] = lower_32_bits(addr);
> +	tx_msg->data[4] = se_get_msg_chksum((u32 *)&tx_msg[0],
> +					    ELE_SERVICE_SWAP_REQ_MSG_SZ);
> +	if (!tx_msg->data[4])
> +		return -EINVAL;
> +
> +	ret = ele_msg_send_rcv(priv, tx_msg, ELE_SERVICE_SWAP_REQ_MSG_SZ,
> +			       rx_msg, ELE_SERVICE_SWAP_RSP_MSG_SZ);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_SERVICE_SWAP_REQ,
> +				      ELE_SERVICE_SWAP_RSP_MSG_SZ, true);
> +	if (ret)
> +		return ret;
> +
> +	if (flag == ELE_IMEM_EXPORT)
> +		ret = rx_msg->data[1];
> +	else
> +		ret = 0;
> +
> +	return ret;
> +}
> +
> +int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr,
> +			dma_addr_t img_addr)
> +{
> +	int ret = 0;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	if (upper_32_bits(contnr_addr) || upper_32_bits(img_addr)) {
> +		dev_err(priv->dev, "Wrong address: %pap %pap\n", &contnr_addr, &img_addr);
> +		return -EINVAL;
> +	}
> +
> +	struct se_api_msg *tx_msg __free(kfree)	=
> +		kzalloc(ELE_FW_AUTH_REQ_SZ, GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	struct se_api_msg *rx_msg __free(kfree) =
> +		kzalloc(ELE_FW_AUTH_RSP_MSG_SZ, GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
> +			    ELE_FW_AUTH_REQ, ELE_FW_AUTH_REQ_SZ, true);
> +
> +	tx_msg->data[0] = lower_32_bits(contnr_addr);
> +	tx_msg->data[1] = 0;
> +	tx_msg->data[2] = lower_32_bits(img_addr);
> +
> +	ret = ele_msg_send_rcv(priv, tx_msg, ELE_FW_AUTH_REQ_SZ, rx_msg,
> +			       ELE_FW_AUTH_RSP_MSG_SZ);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_FW_AUTH_REQ,
> +				      ELE_FW_AUTH_RSP_MSG_SZ, true);
> +
> +	return ret;
> +}
> +
> +int ele_debug_dump(struct se_if_priv *priv)
> +{
> +	bool keep_logging;
> +	int msg_ex_cnt;
> +	int ret = 0;
> +	int i;
> +
> +	if (!priv)
> +		return -EINVAL;
> +
> +	struct se_api_msg *tx_msg __free(kfree) = kzalloc(ELE_DEBUG_DUMP_REQ_SZ,
> +							  GFP_KERNEL);
> +	if (!tx_msg)
> +		return -ENOMEM;
> +
> +	struct se_api_msg *rx_msg __free(kfree)	= kzalloc(ELE_DEBUG_DUMP_RSP_SZ,
> +							  GFP_KERNEL);
> +	if (!rx_msg)
> +		return -ENOMEM;
> +
> +	se_fill_cmd_msg_hdr(priv, &tx_msg->header, ELE_DEBUG_DUMP_REQ,
> +			    ELE_DEBUG_DUMP_REQ_SZ, true);
> +
> +	msg_ex_cnt = 0;
> +	do {
> +		memset(rx_msg, 0x0, ELE_DEBUG_DUMP_RSP_SZ);
> +
> +		ret = ele_msg_send_rcv(priv, tx_msg, ELE_DEBUG_DUMP_REQ_SZ,
> +				       rx_msg, ELE_DEBUG_DUMP_RSP_SZ);
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_DEBUG_DUMP_REQ,
> +					      ELE_DEBUG_DUMP_RSP_SZ, true);
> +		if (ret) {
> +			dev_err(priv->dev, "Dump_Debug_Buffer Error: %x.", ret);
> +			break;
> +		}
> +		keep_logging = (rx_msg->header.size >= (ELE_DEBUG_DUMP_RSP_SZ >> 2) &&
> +				msg_ex_cnt < ELE_MAX_DBG_DMP_PKT);
> +
> +		rx_msg->header.size -= 2;
> +
> +		if (rx_msg->header.size > 2)
> +			rx_msg->header.size--;
> +
> +		for (i = 0; i < rx_msg->header.size; i += 2)
> +			dev_info(priv->dev, "%s%02x_%02x: 0x%08x 0x%08x",
> +				 FW_DBG_DUMP_FIXED_STR,	msg_ex_cnt, i,
> +				 rx_msg->data[i + 1], rx_msg->data[i + 2]);
> +
> +		msg_ex_cnt++;
> +	} while (keep_logging);
> +
> +	return ret;
> +}
> diff --git a/drivers/firmware/imx/ele_base_msg.h b/drivers/firmware/imx/ele_base_msg.h
> new file mode 100644
> index 000000000000..4c3699543e87
> --- /dev/null
> +++ b/drivers/firmware/imx/ele_base_msg.h
> @@ -0,0 +1,98 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2025 NXP
> + *
> + * Header file for the EdgeLock Enclave Base API(s).
> + */
> +
> +#ifndef ELE_BASE_MSG_H
> +#define ELE_BASE_MSG_H
> +
> +#include <linux/device.h>
> +#include <linux/types.h>
> +
> +#include "se_ctrl.h"
> +
> +#define ELE_NONE_VAL			0x0
> +
> +#define ELE_GET_INFO_REQ		0xda
> +#define ELE_GET_INFO_REQ_MSG_SZ		0x10
> +#define ELE_GET_INFO_RSP_MSG_SZ		0x08
> +
> +#define MAX_UID_SIZE                     (16)
> +#define DEV_GETINFO_ROM_PATCH_SHA_SZ     (32)
> +#define DEV_GETINFO_FW_SHA_SZ            (32)
> +#define DEV_GETINFO_OEM_SRKH_SZ          (64)
> +#define DEV_GETINFO_MIN_VER_MASK	0xff
> +#define DEV_GETINFO_MAJ_VER_MASK	0xff00
> +#define ELE_DEV_INFO_EXTRA_SZ		0x60
> +
> +struct dev_info {
> +	u8  cmd;
> +	u8  ver;
> +	u16 length;
> +	u16 soc_id;
> +	u16 soc_rev;
> +	u16 lmda_val;
> +	u8  ssm_state;
> +	u8  dev_atts_api_ver;
> +	u8  uid[MAX_UID_SIZE];
> +	u8  sha_rom_patch[DEV_GETINFO_ROM_PATCH_SHA_SZ];
> +	u8  sha_fw[DEV_GETINFO_FW_SHA_SZ];
> +};
> +
> +struct dev_addn_info {
> +	u8  oem_srkh[DEV_GETINFO_OEM_SRKH_SZ];
> +	u8  trng_state;
> +	u8  csal_state;
> +	u8  imem_state;
> +	u8  reserved2;
> +};
> +
> +struct ele_dev_info {
> +	struct dev_info d_info;
> +	struct dev_addn_info d_addn_info;
> +};
> +
> +#define ELE_GET_INFO_BUFF_SZ		(sizeof(struct ele_dev_info) \
> +						+ ELE_DEV_INFO_EXTRA_SZ)
> +
> +#define GET_SERIAL_NUM_FROM_UID(x, uid_word_sz) ({\
> +	const u32 *__x = (const u32 *)(x); \
> +	size_t __sz = (uid_word_sz); \
> +	((u64)__x[__sz - 1] << 32) | __x[0]; \
> +	})
> +
> +#define ELE_MAX_DBG_DMP_PKT		50
> +#define ELE_DEBUG_DUMP_REQ		0x21
> +#define ELE_DEBUG_DUMP_REQ_SZ		0x4
> +#define ELE_DEBUG_DUMP_RSP_SZ		0x5c
> +
> +#define ELE_PING_REQ			0x01
> +#define ELE_PING_REQ_SZ			0x04
> +#define ELE_PING_RSP_SZ			0x08
> +
> +#define ELE_SERVICE_SWAP_REQ		0xdf
> +#define ELE_SERVICE_SWAP_REQ_MSG_SZ	0x18
> +#define ELE_SERVICE_SWAP_RSP_MSG_SZ	0x0c
> +#define ELE_IMEM_SIZE			0x10000
> +#define ELE_IMEM_STATE_OK		0xca
> +#define ELE_IMEM_STATE_BAD		0xfe
> +#define ELE_IMEM_STATE_WORD		0x27
> +#define ELE_IMEM_STATE_MASK		0x00ff0000
> +#define ELE_IMEM_EXPORT			0x1
> +#define ELE_IMEM_IMPORT			0x2
> +
> +#define ELE_FW_AUTH_REQ			0x02
> +#define ELE_FW_AUTH_REQ_SZ		0x10
> +#define ELE_FW_AUTH_RSP_MSG_SZ		0x08
> +
> +int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info);
> +int ele_fetch_soc_info(struct se_if_priv *priv, void *data);
> +int ele_ping(struct se_if_priv *priv);
> +int ele_service_swap(struct se_if_priv *priv, dma_addr_t addr,
> +		     u32 addr_size, u16 flag);
> +int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr,
> +			dma_addr_t img_addr);
> +int ele_debug_dump(struct se_if_priv *priv);
> +#endif
> diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c
> new file mode 100644
> index 000000000000..3f5f78df49b5
> --- /dev/null
> +++ b/drivers/firmware/imx/ele_common.c
> @@ -0,0 +1,448 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#include "ele_base_msg.h"
> +#include "ele_common.h"
> +
> +/*
> + * se_get_msg_chksum() - to calculate checksum word by word.
> + *
> + * @msg : reference to the input msg-data.
> + * @msg_len : reference to the input msg-data length in bytes.
> + *            Includes extra 4 bytes (or 1 words) chksum.
> + *
> + * This function returns the checksum calculated by ORing word by word.
> + *
> + * Return:
> + *  0: if the input length is not 4 byte aligned, or num of words < 5.
> + *  chksum: calculated word by word.
> + */
> +u32 se_get_msg_chksum(u32 *msg, u32 msg_len)
> +{
> +	u32 nb_words = msg_len / (u32)sizeof(u32);
> +	u32 chksum = 0;
> +	u32 i;
> +
> +	if (nb_words < 5)
> +		return chksum;
> +
> +	if (msg_len % SE_MSG_WORD_SZ) {
> +		pr_err("Msg-len is not 4-byte aligned.");
> +		return chksum;
> +	}
> +
> +	/* nb_words include one checksum word, so skip it. */
> +	nb_words--;
> +
> +	for (i = 0; i < nb_words; i++)
> +		chksum ^= *(msg + i);
> +
> +	return chksum;
> +}
> +
> +int ele_msg_rcv(struct se_if_priv *priv, struct se_clbk_handle *se_clbk_hdl)
> +{
> +	bool wait_uninterruptible = false;
> +	unsigned long remaining_jiffies;
> +	unsigned long flags;
> +	int ret;
> +
> +	remaining_jiffies = MAX_SCHEDULE_TIMEOUT;
> +	do {
> +		if (wait_uninterruptible)
> +			ret = wait_for_completion_timeout(&se_clbk_hdl->done,
> +							  remaining_jiffies);
> +		else
> +			ret = wait_for_completion_interruptible_timeout(&se_clbk_hdl->done,
> +									remaining_jiffies);
> +		if (ret == -ERESTARTSYS) {
> +			/*
> +			 * Record that a signal was observed, then continue waiting non-
> +			 * interruptibly until the response arrives or the timeout
> +			 * expires. The caller can surface the interruption to userspace
> +			 * after the protocol transaction is brought back to a
> +			 * synchronized state.
> +			 */
> +			if (priv->waiting_rsp_clbk_hdl.rx_msg) {
> +				WRITE_ONCE(se_clbk_hdl->signal_rcvd, true);
> +				wait_uninterruptible = true;
> +				continue;
> +			}
> +			break;
> +		}
> +
> +		if (ret == 0) {
> +			/*
> +			 * The response buffer belongs to the caller of ele_msg_send_rcv()
> +			 * and may be freed as soon as this function returns. Clear rx_msg
> +			 * under clbk_rx_lock so that a late se_if_rx_callback() can
> +			 * observe that the waiter has timed out and must not copy into
> +			 * the stale buffer.
> +			 *
> +			 * If the completion has not yet been signaled, mark the firmware
> +			 * path busy. This acts as a circuit breaker: reject new
> +			 * command/response transactions until the delayed response
> +			 * arrives and the callback closes the breaker.
> +			 */
> +
> +			spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags);
> +			se_clbk_hdl->rx_msg = NULL;
> +			if (!completion_done(&se_clbk_hdl->done))
> +				atomic_set(&priv->fw_busy, 1);
> +
> +			spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags);
> +			ret = -ETIMEDOUT;
> +			dev_err(priv->dev,
> +				"Fatal Error: SE interface: %s0, hangs indefinitely.\n",
> +				get_se_if_name(priv->if_defs->se_if_type));
> +			break;
> +		}
> +		ret = se_clbk_hdl->rx_msg_sz;
> +		break;
> +	} while (ret < 0);
> +
> +	return ret;
> +}
> +
> +int ele_msg_send(struct se_if_priv *priv,
> +		 void *tx_msg,
> +		 int tx_msg_sz)
> +{
> +	struct se_msg_hdr *header = tx_msg;
> +	int err;
> +
> +	/*
> +	 * Check that the size passed as argument matches the size
> +	 * carried in the message.
> +	 */
> +	if (header->size << 2 != tx_msg_sz) {
> +		dev_err(priv->dev,
> +			"User buf hdr: 0x%x, sz mismatced with input-sz (%d != %d).",
> +			*(u32 *)header, header->size << 2, tx_msg_sz);
> +		return -EINVAL;
> +	}
> +
> +	err = mbox_send_message(priv->tx_chan, tx_msg);
> +	if (err < 0) {
> +		dev_err(priv->dev, "Error: mbox_send_message failure.\n");
> +		return err;
> +	}
> +
> +	return tx_msg_sz;
> +}
> +
> +/* API used for send/receive blocking call. */
> +int ele_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz,
> +		     void *rx_msg, int exp_rx_msg_sz)
> +{
> +	unsigned long flags;
> +	int err;
> +
> +	guard(mutex)(&priv->se_if_cmd_lock);
> +
> +	if (atomic_read(&priv->fw_busy)) {
> +		dev_dbg(priv->dev, "ELE became unresponsive.\n");
> +		return -EBUSY;
> +	}
> +	reinit_completion(&priv->waiting_rsp_clbk_hdl.done);
> +	priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz;
> +	priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg;
> +
> +	err = ele_msg_send(priv, tx_msg, tx_msg_sz);
> +	if (err < 0)
> +		goto clear_waiter;
> +
> +	err = ele_msg_rcv(priv, &priv->waiting_rsp_clbk_hdl);
> +
> +	if (priv->waiting_rsp_clbk_hdl.signal_rcvd) {
> +		/*
> +		 * A signal was received after the command was sent. ele_msg_rcv()
> +		 * kept waiting until the FW/kernel protocol was synchronized again.
> +		 * If the transaction itself completed successfully, report the
> +		 * deferred signal to userspace using normal syscall-restart semantics.
> +		 * Do not hide real firmware/protocol errors such as -ETIMEDOUT.
> +		 */
> +		if (err > 0)
> +			err = -ERESTARTSYS;
> +		priv->waiting_rsp_clbk_hdl.signal_rcvd = false;
> +		dev_err(priv->dev, "Err[0x%x]:Interrupted by signal.", err);
> +	}
> +
> +clear_waiter:
> +	spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags);
> +	priv->waiting_rsp_clbk_hdl.rx_msg = NULL;
> +	priv->waiting_rsp_clbk_hdl.rx_msg_sz = 0;
> +	spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags);
> +
> +	return err;
> +}
> +
> +static bool check_hdr_exception_for_sz(struct se_if_priv *priv,
> +				       struct se_msg_hdr *header)
> +{
> +	/*
> +	 * List of API(s) header that can be accepte variable length
> +	 * response buffer.
> +	 */
> +	if (header->command == ELE_DEBUG_DUMP_REQ &&
> +	    header->ver == priv->if_defs->base_api_ver &&
> +	    header->size >= 2 && header->size <= (ELE_DEBUG_DUMP_RSP_SZ / 4))
> +		return true;
> +
> +	return false;
> +}
> +
> +/*
> + * Callback called by mailbox FW, when data is received.
> + */
> +void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
> +{
> +	struct se_clbk_handle *se_clbk_hdl;
> +	struct device *dev = mbox_cl->dev;
> +	struct se_msg_hdr *header;
> +	bool sz_mismatch = false;
> +	struct se_if_priv *priv;
> +	unsigned long flags;
> +	u32 rx_msg_sz;
> +
> +	priv = dev_get_drvdata(dev);
> +
> +	/* The function can be called with NULL msg */
> +	if (!msg) {
> +		dev_err(dev, "Message is invalid\n");
> +		return;
> +	}
> +
> +	header = msg;
> +	rx_msg_sz = header->size << 2;
> +
> +	/* Incoming command: wake up the receiver if any. */
> +	if (header->tag == priv->if_defs->cmd_tag) {
> +		se_clbk_hdl = &priv->cmd_receiver_clbk_hdl;
> +		spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags);
> +		if (!se_clbk_hdl->rx_msg) {
> +			spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags);
> +			dev_warn(dev, "No command receiver registered for message: %.8x\n",
> +				 *((u32 *)header));
> +			return;
> +		}
> +
> +		/*
> +		 * cmd_tag messages are delivered only to the explicitly registered
> +		 * command receiver. Unlike the synchronous response waiter path, the
> +		 * command receiver uses a dedicated long-lived buffer installed by
> +		 * SE_IOCTL_ENABLE_CMD_RCV and is not subject to the timeout/circuit-
> +		 * breaker handling used for rsp_tag messages.
> +		 */
> +		dev_dbg(dev, "Selecting cmd receiver: for mesg header:0x%x.",
> +			*(u32 *)header);
> +
> +		/*
> +		 * Pre-allocated buffer of MAX_NVM_MSG_LEN
> +		 * as the NVM command are initiated by FW.
> +		 * Size is revealed as part of this call function.
> +		 */
> +
> +		if (rx_msg_sz > MAX_NVM_MSG_LEN) {
> +			/* Store the response buffer maxsize in local variable.*/
> +			rx_msg_sz = MAX_NVM_MSG_LEN;
> +			sz_mismatch = true;
> +		}
> +
> +		se_clbk_hdl->rx_msg_sz = rx_msg_sz;
> +		memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz);
> +		complete(&se_clbk_hdl->done);
> +		spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags);
> +		if (sz_mismatch)
> +			dev_err(dev,
> +				"CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n",
> +				*(u32 *)header,
> +				(header->size << 2), rx_msg_sz);
> +	} else if (header->tag == priv->if_defs->rsp_tag) {
> +		bool exception_for_sz_mismatch = check_hdr_exception_for_sz(priv, header);
> +		u32 exp_rx_msg_sz = 0;
> +
> +		/*
> +		 * waiting_rsp_clbk_hdl.rx_msg is owned by the synchronous sender in
> +		 * ele_msg_send_rcv(). After timeout or error, that path clears rx_msg
> +		 * under clbk_rx_lock before returning to its caller, which may then free
> +		 * the buffer. Check rx_msg under the same lock here so a delayed response
> +		 * can be detected and dropped instead of copying into freed memory.
> +		 *
> +		 * A late response also closes the firmware-busy circuit breaker, allowing
> +		 * future command/response transactions to proceed again.
> +		 */
> +		se_clbk_hdl = &priv->waiting_rsp_clbk_hdl;
> +		exp_rx_msg_sz = se_clbk_hdl->rx_msg_sz;
> +		spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags);
> +		if (!se_clbk_hdl->rx_msg) {
> +			/* Close circuit breaker on spinlock race */
> +			atomic_set(&priv->fw_busy, 0);
> +			spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags);
> +			dev_info(dev, "ELE responded (late), recovery FW available.");
> +			return;
> +		}
> +		dev_dbg(dev, "Selecting resp waiter: for mesg header:0x%x.",
> +			*(u32 *)header);
> +
> +		/*
> +		 * For rsp_tag traffic, the sender provides the expected response
> +		 * buffer size. If firmware returns a different size, clamp the copy
> +		 * length to the caller's buffer capacity before memcpy() and report the
> +		 * mismatch after dropping the spinlock.
> +		 */
> +		if (rx_msg_sz != exp_rx_msg_sz) {
> +			if (!exception_for_sz_mismatch)
> +				sz_mismatch = true;
> +
> +			se_clbk_hdl->rx_msg_sz = min(rx_msg_sz, exp_rx_msg_sz);
> +		}
> +		memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz);
> +		complete(&se_clbk_hdl->done);
> +		spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags);
> +
> +		if (sz_mismatch)
> +			dev_err(dev,
> +				"Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n",
> +				*(u32 *)header,
> +				(header->size << 2), exp_rx_msg_sz);
> +	} else {
> +		dev_err(dev, "Failed to select a device for message: %.8x\n",
> +			*((u32 *)header));
> +	}
> +}
> +
> +int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg,
> +			    u8 msg_id, u8 sz, bool is_base_api)
> +{
> +	struct se_msg_hdr *header = &msg->header;
> +	u32 status;
> +
> +	if (header->tag != priv->if_defs->rsp_tag) {
> +		dev_err(priv->dev, "MSG[0x%x] Hdr: Resp tag mismatch. (0x%x != 0x%x)",
> +			msg_id, header->tag, priv->if_defs->rsp_tag);
> +		return -EINVAL;
> +	}
> +
> +	if (header->command != msg_id) {
> +		dev_err(priv->dev, "MSG Header: Cmd id mismatch. (0x%x != 0x%x)",
> +			header->command, msg_id);
> +		return -EINVAL;
> +	}
> +
> +	if ((sz % 4) || (header->size != (sz >> 2) &&
> +			 !check_hdr_exception_for_sz(priv, header))) {
> +		dev_err(priv->dev, "MSG[0x%x] Hdr: Cmd size mismatch. (0x%x != 0x%x)",
> +			msg_id, header->size, (sz >> 2));
> +		return -EINVAL;
> +	}
> +
> +	if (is_base_api && header->ver != priv->if_defs->base_api_ver) {
> +		dev_err(priv->dev,
> +			"MSG[0x%x] Hdr: Base API Vers mismatch. (0x%x != 0x%x)",
> +			msg_id, header->ver, priv->if_defs->base_api_ver);
> +		return -EINVAL;
> +	} else if (!is_base_api && header->ver != priv->if_defs->fw_api_ver) {
> +		dev_err(priv->dev,
> +			"MSG[0x%x] Hdr: FW API Vers mismatch. (0x%x != 0x%x)",
> +			msg_id, header->ver, priv->if_defs->fw_api_ver);
> +		return -EINVAL;
> +	}
> +
> +	status = RES_STATUS(msg->data[0]);
> +	if (status != priv->if_defs->success_tag) {
> +		dev_err(priv->dev, "Command Id[%x], Response Failure = 0x%x",
> +			header->command, status);
> +		return -EPERM;
> +	}
> +
> +	return 0;
> +}
> +
> +int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem)
> +{
> +	struct ele_dev_info s_info = {0};
> +	int ret;
> +
> +	ret = ele_get_info(priv, &s_info);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to get info from ELE.\n");
> +		return ret;
> +	}
> +
> +	/* Check for the imem-state before continue to save imem state. */
> +	if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD)
> +		return 0;
> +
> +	/*
> +	 * EXPORT command will save encrypted IMEM to given address,
> +	 * so later in resume, IMEM can be restored from the given
> +	 * address.
> +	 *
> +	 * Size must be at least 64 kB.
> +	 */
> +	ret = ele_service_swap(priv, imem->daddr, ELE_IMEM_SIZE, ELE_IMEM_EXPORT);
> +	if (ret < 0) {
> +		dev_err(priv->dev, "Failed to export IMEM.");
> +		imem->size = 0;
> +	} else {
> +		dev_dbg(priv->dev,
> +			"Exported %d bytes of encrypted IMEM.",
> +			ret);
> +		imem->size = ret;
> +	}
> +
> +	return ret > 0 ? 0 : ret;
> +}
> +
> +int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem)
> +{
> +	struct ele_dev_info s_info;
> +	int ret;
> +
> +	/* get info from ELE */
> +	ret = ele_get_info(priv, &s_info);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to get info from ELE.");
> +		return ret;
> +	}
> +	imem->state = s_info.d_addn_info.imem_state;
> +
> +	/* Check for the imem-state and imem-size before continue to
> +	 * restore imem state.
> +	 */
> +	if (s_info.d_addn_info.imem_state != ELE_IMEM_STATE_BAD || !imem->size)
> +		return -EIO;
> +
> +	/*
> +	 * IMPORT command will restore IMEM from the given
> +	 * address, here size is the actual size returned by ELE
> +	 * during the export operation
> +	 */
> +	ret = ele_service_swap(priv, imem->daddr, imem->size, ELE_IMEM_IMPORT);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to import IMEM");
> +		return ret;
> +	}
> +
> +	/*
> +	 * After importing IMEM, check if IMEM state is equal to 0xCA
> +	 * to ensure IMEM is fully loaded and
> +	 * ELE functionality can be used.
> +	 */
> +	ret = ele_get_info(priv, &s_info);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to get info from ELE.");
> +		return ret;
> +	}
> +	imem->state = s_info.d_addn_info.imem_state;
> +
> +	if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_OK)
> +		dev_dbg(priv->dev, "Successfully restored IMEM.");
> +	else
> +		dev_err(priv->dev, "Failed to restore IMEM.");
> +
> +	return ret;
> +}
> diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h
> new file mode 100644
> index 000000000000..0365759fdd12
> --- /dev/null
> +++ b/drivers/firmware/imx/ele_common.h
> @@ -0,0 +1,43 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2025 NXP
> + */
> +
> +#ifndef __ELE_COMMON_H__
> +#define __ELE_COMMON_H__
> +
> +#include "se_ctrl.h"
> +
> +#define ELE_SUCCESS_IND			0xD6
> +
> +#define IMX_ELE_FW_DIR                 "imx/ele/"
> +
> +u32 se_get_msg_chksum(u32 *msg, u32 msg_len);
> +
> +int ele_msg_rcv(struct se_if_priv *priv, struct se_clbk_handle *se_clbk_hdl);
> +
> +int ele_msg_send(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz);
> +
> +int ele_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz,
> +		     void *rx_msg, int exp_rx_msg_sz);
> +
> +void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg);
> +
> +int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg,
> +			    u8 msg_id, u8 sz, bool is_base_api);
> +
> +/* Fill a command message header with a given command ID and length in bytes. */
> +static inline void se_fill_cmd_msg_hdr(struct se_if_priv *priv, struct se_msg_hdr *hdr,
> +				       u8 cmd, u32 len, bool is_base_api)
> +{
> +	hdr->tag = priv->if_defs->cmd_tag;
> +	hdr->ver = (is_base_api) ? priv->if_defs->base_api_ver : priv->if_defs->fw_api_ver;
> +	hdr->command = cmd;
> +	hdr->size = len >> 2;
> +}
> +
> +int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem);
> +
> +int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem);
> +
> +#endif /*__ELE_COMMON_H__ */
> diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
> new file mode 100644
> index 000000000000..7cb98a373334
> --- /dev/null
> +++ b/drivers/firmware/imx/se_ctrl.c
> @@ -0,0 +1,410 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2026 NXP
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/dev_printk.h>
> +#include <linux/dma-direct.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/errno.h>
> +#include <linux/export.h>
> +#include <linux/firmware.h>
> +#include <linux/firmware/imx/se_api.h>
> +#include <linux/genalloc.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/miscdevice.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_reserved_mem.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/sys_soc.h>

Please don't add new #includes for <linux/mod_devicetable.h>.
<linux/platform_device.h> already provides of_device_id.

> +static const struct of_device_id se_match[] = {
> +	{ .compatible = "fsl,imx8ulp-se-ele-hsm", .data = &imx8ulp_se_ele_hsm },
> +	{ .compatible = "fsl,imx93-se-ele-hsm", .data = &imx93_se_ele_hsm },
> +	{}

{ } is the more typical way for the list terminator. (That's a nitpick.)

> +};
> [...]
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int se_suspend(struct device *dev)
> +{
> +	struct se_if_priv *priv = dev_get_drvdata(dev);
> +	struct se_fw_load_info *load_fw;
> +	int ret = 0;
> +
> +	load_fw = get_load_fw_instance(priv);
> +
> +	if (load_fw->imem_mgmt) {
> +		ret = se_save_imem_state(priv, &load_fw->imem);
> +		if (ret)
> +			dev_warn(dev, "Failure saving IMEM state[0x%x]", ret);
> +	}
> +
> +	return 0;
> +}
> +
> +static int se_resume(struct device *dev)
> +{
> +	struct se_if_priv *priv = dev_get_drvdata(dev);
> +	struct se_fw_load_info *load_fw;
> +	int ret = 0;
> +
> +	load_fw = get_load_fw_instance(priv);
> +
> +	if (load_fw->imem_mgmt) {
> +		ret = se_restore_imem_state(priv, &load_fw->imem);
> +		if (ret)
> +			dev_warn(dev, "Failure restoring IMEM state[0x%x]", ret);
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops se_pm = {
> +	SET_SYSTEM_SLEEP_PM_OPS(se_suspend, se_resume)
> +};
> +
> +#define SE_PM_OPS	(&se_pm)
> +#else
> +#define SE_PM_OPS	NULL
> +#endif

If you use DEFINE_SIMPLE_DEV_PM_OPS() you can drop the #ifdeffery. (But
double check this does what you want.)

> +static struct platform_driver se_driver = {
> +	.driver = {
> +		.name = "fsl-se",
> +		.of_match_table = se_match,
> +		.pm = SE_PM_OPS,
> +	},
> +	.probe = se_if_probe,
> +};
> +MODULE_DEVICE_TABLE(of, se_match);

MODULE_DEVICE_TABLE belongs to directly after the table.
> +
> +module_platform_driver(se_driver);

Please put this after se_driver (without a newline).

> +MODULE_AUTHOR("Pankaj Gupta <pankaj.gupta@nxp.com>");
> +MODULE_DESCRIPTION("iMX Secure Enclave Driver.");
> +MODULE_LICENSE("GPL");

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH] Documentation: warn users not to use select on choice options in Kconfig
From: Julian Braha @ 2026-07-15 22:01 UTC (permalink / raw)
  To: nathan, nsc, corbet, skhan
  Cc: arnd, stefan.hengelein, linux-kbuild, linux-kernel, linux-doc,
	nico, officialnaumansabir, rdunlap, vegard.nossum, kees, tj,
	Julian Braha

Hengelein's master thesis about Kconfig from 2015 wrote that 'select'
does not work on member options inside of a 'choice'.

So I've re-implemented his check as part of kconfirm:
https://github.com/julianbraha/kconfirm

and discovered several instances of these dead selects in use, and
fixing them is not always trivial. For example, see:
https://lore.kernel.org/all/a3b7a752-8cc4-492a-bb62-43121b852c41@app.fastmail.com/

Let's add a warning to the documentation (a place where developers
are more likely to see it than a master's thesis...)

Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
 Documentation/kbuild/kconfig-language.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
index d9338407c1c6..ab2822d7ca1c 100644
--- a/Documentation/kbuild/kconfig-language.rst
+++ b/Documentation/kbuild/kconfig-language.rst
@@ -164,6 +164,11 @@ applicable everywhere (see syntax).
 	That will limit the usefulness but on the other hand avoid
 	the illegal configurations all over.
 
+	select should also not be used on the member options of a choice.
+	Selecting a choice option will do nothing (dead code). Instead,
+	consider making these a dependency, or using the defaults of the
+	choice to enable the member option when it's needed.
+
 	If "select" <symbol> is followed by "if" <expr>, <symbol> will be
 	selected by the logical AND of the value of the current menu symbol
 	and <expr>. This means, the lower limit can be downgraded due to the
-- 
2.54.0


^ permalink raw reply related

* [PATCH bpf-next v5 8/8] selftests: net: add test for XDP_PASS skb checksum invalidation
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Lorenzo Bianconi
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-0-623d5c0d0ab7@kernel.org>

Add a test that verifies skb->ip_summed is set to CHECKSUM_NONE
when a device running in XDP mode creates an skb from a xdp_buff
if the attached ebpf program returns an XDP_PASS.
The test attaches an XDP program returning XDP_PASS, and a TC
ingress program that runs the bpf_skb_rx_checksum() kfunc to
inspect the resulting skb. After XDP_PASS the driver must invalidate
any previously computed hardware RX checksum since XDP may have
modified the packet data.
The BPF program counts packets per checksum type in a map, and the
test runner verifies that after sending traffic the CHECKSUM_NONE
counter is non-zero while CHECKSUM_UNNECESSARY and CHECKSUM_COMPLETE
counters are zero.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 Documentation/networking/xdp-rx-metadata.rst       |  5 ++
 .../selftests/drivers/net/hw/xdp_metadata.py       | 55 +++++++++++++++-
 .../selftests/net/lib/skb_metadata_csum.bpf.c      | 73 ++++++++++++++++++++++
 3 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/Documentation/networking/xdp-rx-metadata.rst b/Documentation/networking/xdp-rx-metadata.rst
index 93918b3769a3..7434ac98242a 100644
--- a/Documentation/networking/xdp-rx-metadata.rst
+++ b/Documentation/networking/xdp-rx-metadata.rst
@@ -90,6 +90,11 @@ conversion, and the XDP metadata is not used by the kernel when building
 ``skbs``. However, TC-BPF programs can access the XDP metadata area using
 the ``data_meta`` pointer.
 
+If a driver is running in XDP mode, any existing hardware RX checksum
+(``CHECKSUM_UNNECESSARY`` or ``CHECKSUM_COMPLETE``) must be invalidated
+by setting ``skb->ip_summed`` to ``CHECKSUM_NONE`` before passing the
+skb to the kernel, since XDP may have modified the packet data.
+
 In the future, we'd like to support a case where an XDP program
 can override some of the metadata used for building ``skbs``.
 
diff --git a/tools/testing/selftests/drivers/net/hw/xdp_metadata.py b/tools/testing/selftests/drivers/net/hw/xdp_metadata.py
old mode 100644
new mode 100755
index 33a1985356d9..8ccd34b776b4
--- a/tools/testing/selftests/drivers/net/hw/xdp_metadata.py
+++ b/tools/testing/selftests/drivers/net/hw/xdp_metadata.py
@@ -8,12 +8,13 @@ These tests load device-bound XDP programs from xdp_metadata.bpf.o
 that call metadata kfuncs, send traffic, and verify the extracted
 metadata via BPF maps.
 """
+import json
 from lib.py import ksft_run, ksft_eq, ksft_exit, ksft_ge, ksft_ne, ksft_pr
 from lib.py import KsftNamedVariant, ksft_variants
 from lib.py import CmdExitFailure, KsftSkipEx, NetDrvEpEnv
 from lib.py import NetdevFamily
 from lib.py import bkg, cmd, rand_port, wait_port_listen
-from lib.py import ip, bpftool, defer
+from lib.py import ip, bpftool, defer, ethtool
 from lib.py import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
 
 
@@ -130,6 +131,57 @@ def test_xdp_rss_hash(cfg, proto):
             f"RSS hash type should include L4 for {proto.upper()} traffic")
 
 
+def test_xdp_pass_rx_csum(cfg):
+    """Test xdp_pass sets CHECKSUM_NONE on the resulting skb.
+
+    Attaches an XDP program that returns XDP_PASS and a TC ingress
+    program that checks skb->ip_summed via bpf_skb_rx_checksum().
+    Verifies the value is CHECKSUM_NONE.
+    """
+
+    bpf_obj = cfg.net_lib_dir / "skb_metadata_csum.bpf.o"
+    xdp_obj = cfg.net_lib_dir / "xdp_dummy.bpf.o"
+
+    # GRO may overwrite skb->ip_summed after the driver sets it,
+    # so disable it to preserve the checksum set by the driver.
+    ethtool(f"-K {cfg.ifname} gro off")
+    defer(ethtool, f"-K {cfg.ifname} gro on")
+    ip(f"link set dev {cfg.ifname} xdp obj {xdp_obj} sec xdp")
+    defer(ip, f"link set dev {cfg.ifname} xdp off")
+
+    qdiscs = json.loads(cmd(f"tc -j qdisc show dev {cfg.ifname}").stdout)
+    if not any(q['kind'] == 'clsact' for q in qdiscs):
+        cmd(f"tc qdisc add dev {cfg.ifname} clsact")
+        defer(cmd, f"tc qdisc del dev {cfg.ifname} clsact")
+    cmd(f"tc filter add dev {cfg.ifname} ingress bpf da obj {bpf_obj} sec tc")
+
+    progs = bpftool("prog list", json=True)
+    tc_prog_id = None
+    for p in progs:
+        if p.get("name") == "tc_check_csum":
+            tc_prog_id = p["id"]
+            break
+
+    if tc_prog_id is None:
+        raise KsftSkipEx("Could not find tc_check_csum BPF program")
+
+    maps = bpf_prog_map_ids(tc_prog_id)
+    csum_map_id = maps.get("map_csum_result")
+    if csum_map_id is None:
+        raise KsftSkipEx("Could not find map_csum_result map")
+
+    for _ in range(10):
+        _send_probe(cfg, 12345, proto="udp")
+
+    result = bpf_map_dump(csum_map_id)
+    csum_none = result.get(0, 0)
+    csum_unnecessary = result.get(1, 0)
+    csum_complete = result.get(2, 0)
+    ksft_ge(csum_none, 1, "skb->ip_summed should be CHECKSUM_NONE after XDP_PASS")
+    ksft_eq(csum_unnecessary, 0, "CHECKSUM_UNNECESSARY should not be set")
+    ksft_eq(csum_complete, 0, "CHECKSUM_COMPLETE should not be set")
+
+
 def main():
     """Run XDP metadata kfunc tests against a real device."""
     with NetDrvEpEnv(__file__) as cfg:
@@ -137,6 +189,7 @@ def main():
         ksft_run(
             [
                 test_xdp_rss_hash,
+                test_xdp_pass_rx_csum,
             ],
             args=(cfg,))
     ksft_exit()
diff --git a/tools/testing/selftests/net/lib/skb_metadata_csum.bpf.c b/tools/testing/selftests/net/lib/skb_metadata_csum.bpf.c
new file mode 100644
index 000000000000..6a953c4acfe7
--- /dev/null
+++ b/tools/testing/selftests/net/lib/skb_metadata_csum.bpf.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/ipv6.h>
+#include <linux/pkt_cls.h>
+#include <linux/udp.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+#define UDP_PORT 12345
+
+enum skb_csum {
+	SKB_CSUM_NONE		= 0,
+	SKB_CSUM_UNNECESSARY	= 1,
+	SKB_CSUM_COMPLETE	= 2,
+	SKB_CSUM_PARTIAL	= 3,
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, SKB_CSUM_PARTIAL);
+	__type(key, __u32);
+	__type(value, __u64);
+} map_csum_result SEC(".maps");
+
+extern int bpf_skb_rx_checksum(struct __sk_buff *skb, __u32 *ip_summed,
+				__u32 *csum_meta) __ksym;
+
+SEC("tc")
+int tc_check_csum(struct __sk_buff *skb)
+{
+	void *data_end = (void *)(long)skb->data_end;
+	void *data = (void *)(long)skb->data;
+	__u32 ip_summed, csum_meta;
+	struct ethhdr *eth = data;
+	struct ipv6hdr *ip6;
+	struct udphdr *udp;
+
+	if ((void *)(eth + 1) > data_end)
+		return TC_ACT_OK;
+
+	if (eth->h_proto != bpf_htons(ETH_P_IPV6))
+		return TC_ACT_OK;
+
+	ip6 = (void *)(eth + 1);
+	if ((void *)(ip6 + 1) > data_end)
+		return TC_ACT_OK;
+
+	if (ip6->nexthdr != IPPROTO_UDP)
+		return TC_ACT_OK;
+
+	udp = (void *)(ip6 + 1);
+	if ((void *)(udp + 1) > data_end)
+		return TC_ACT_OK;
+
+	if (udp->dest != bpf_htons(UDP_PORT))
+		return TC_ACT_OK;
+
+	bpf_skb_rx_checksum(skb, &ip_summed, &csum_meta);
+	if (ip_summed < SKB_CSUM_PARTIAL) {
+		__u64 *cnt;
+
+		cnt = bpf_map_lookup_elem(&map_csum_result, &ip_summed);
+		if (cnt)
+			__sync_fetch_and_add(cnt, 1);
+	}
+
+	return TC_ACT_OK;
+}
+
+char _license[] SEC("license") = "GPL";

-- 
2.55.0


^ permalink raw reply related

* [PATCH bpf-next v5 7/8] selftests/bpf: Add test for bpf_skb_rx_checksum kfunc
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Lorenzo Bianconi
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-0-623d5c0d0ab7@kernel.org>

Add a selftest for the newly added bpf_skb_rx_checksum() kfunc.
The test consists of a TC BPF program that calls the kfunc and
records which checksum type each packet has in a per-type counter
map, and a userspace test runner that exercises two scenarios:

- csum_none: runs with bpf_prog_test_run_opts (no special flags),
  verifies all packets are reported as CHECKSUM_NONE.
- csum_complete: runs with BPF_F_TEST_SKB_CHECKSUM_COMPLETE flag,
  verifies all packets are reported as CHECKSUM_COMPLETE.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 tools/testing/selftests/bpf/bpf_kfuncs.h           |  8 ++++
 .../selftests/bpf/prog_tests/skb_rx_checksum.c     | 50 ++++++++++++++++++++++
 .../testing/selftests/bpf/progs/skb_rx_checksum.c  | 33 ++++++++++++++
 tools/testing/selftests/bpf/skb_rx_checksum.h      |  8 ++++
 4 files changed, 99 insertions(+)

diff --git a/tools/testing/selftests/bpf/bpf_kfuncs.h b/tools/testing/selftests/bpf/bpf_kfuncs.h
index ae71e9b69051..d03572e26df2 100644
--- a/tools/testing/selftests/bpf/bpf_kfuncs.h
+++ b/tools/testing/selftests/bpf/bpf_kfuncs.h
@@ -64,6 +64,14 @@ struct bpf_tcp_req_attrs;
 extern int bpf_sk_assign_tcp_reqsk(struct __sk_buff *skb, struct sock *sk,
 				   struct bpf_tcp_req_attrs *attrs, int attrs__sz) __ksym;
 
+/* Description
+ *  Read skb RX checksum info (ip_summed and csum_meta).
+ * Returns
+ *  0 on success
+ */
+extern int bpf_skb_rx_checksum(struct __sk_buff *skb, __u32 *ip_summed,
+			       __u32 *csum_meta) __ksym;
+
 void *bpf_cast_to_kern_ctx(void *) __ksym;
 
 extern void *bpf_rdonly_cast(const void *obj, __u32 btf_id) __ksym __weak;
diff --git a/tools/testing/selftests/bpf/prog_tests/skb_rx_checksum.c b/tools/testing/selftests/bpf/prog_tests/skb_rx_checksum.c
new file mode 100644
index 000000000000..d71ab7c70b68
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/skb_rx_checksum.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include <network_helpers.h>
+#include "skb_rx_checksum.skel.h"
+#include "skb_rx_checksum.h"
+
+#define TX_PACKETS 3
+
+static int run_test(__u32 flags, enum skb_csum expected_csum)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts,
+		.data_in = &pkt_v4,
+		.data_size_in = sizeof(pkt_v4),
+		.repeat = TX_PACKETS,
+		.flags = flags,
+	);
+	int prog_fd, err, key = expected_csum;
+	struct skb_rx_checksum *skel;
+	__u64 cnt;
+
+	skel = skb_rx_checksum__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
+		return -1;
+
+	prog_fd = bpf_program__fd(skel->progs.tc_rx_csum);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	if (!ASSERT_OK(err, "test_run"))
+		goto cleanup;
+
+	if (!ASSERT_EQ(topts.retval, 0, "retval"))
+		goto cleanup;
+
+	err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.csum_cnt), &key, &cnt);
+	if (!ASSERT_OK(err, "map_lookup"))
+		goto cleanup;
+
+	ASSERT_EQ(cnt, TX_PACKETS, "csum_cnt");
+cleanup:
+	skb_rx_checksum__destroy(skel);
+	return 0;
+}
+
+void test_skb_rx_checksum(void)
+{
+	if (test__start_subtest("csum_none"))
+		run_test(0, SKB_CSUM_NONE);
+
+	if (test__start_subtest("csum_complete"))
+		run_test(BPF_F_TEST_SKB_CHECKSUM_COMPLETE, SKB_CSUM_COMPLETE);
+}
diff --git a/tools/testing/selftests/bpf/progs/skb_rx_checksum.c b/tools/testing/selftests/bpf/progs/skb_rx_checksum.c
new file mode 100644
index 000000000000..dc4e192905d5
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/skb_rx_checksum.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <linux/pkt_cls.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_kfuncs.h"
+#include "skb_rx_checksum.h"
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, SKB_CSUM_PARTIAL);
+	__type(key, __u32);
+	__type(value, __u64);
+} csum_cnt SEC(".maps");
+
+SEC("tc")
+int tc_rx_csum(struct __sk_buff *skb)
+{
+	enum skb_csum ip_summed;
+	__u32 csum_meta;
+	__u64 *cnt;
+
+	bpf_skb_rx_checksum(skb, &ip_summed, &csum_meta);
+	if (ip_summed < SKB_CSUM_PARTIAL) {
+		cnt = bpf_map_lookup_elem(&csum_cnt, &ip_summed);
+		if (cnt)
+			__sync_fetch_and_add(cnt, 1);
+	}
+
+	return TC_ACT_OK;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/skb_rx_checksum.h b/tools/testing/selftests/bpf/skb_rx_checksum.h
new file mode 100644
index 000000000000..60aad3561843
--- /dev/null
+++ b/tools/testing/selftests/bpf/skb_rx_checksum.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+enum skb_csum {
+	SKB_CSUM_NONE		= 0,
+	SKB_CSUM_UNNECESSARY	= 1,
+	SKB_CSUM_COMPLETE	= 2,
+	SKB_CSUM_PARTIAL	= 3,
+};

-- 
2.55.0


^ permalink raw reply related

* [PATCH bpf-next v5 6/8] net: add bpf_skb_rx_checksum kfunc to read skb checksum metadata
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Lorenzo Bianconi
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-0-623d5c0d0ab7@kernel.org>

Add a new BPF kfunc, bpf_skb_rx_checksum(), that allows TC and other
skb-attached BPF programs to read the skb->ip_summed field and
associated checksum metadata. This is needed because the existing
bpf_csum_level() helper only distinguishes CHECKSUM_UNNECESSARY
from all other states, making it unsuitable when the caller needs
to differentiate CHECKSUM_NONE from CHECKSUM_COMPLETE (e.g. after
XDP_PASS where the driver may have set either).

The kfunc writes two output values:
  - ip_summed: the raw skb->ip_summed value
               (CHECKSUM_NONE=0, CHECKSUM_UNNECESSARY=1,
                CHECKSUM_COMPLETE=2, CHECKSUM_PARTIAL=3)
  - csum_meta: CHECKSUM_COMPLETE -> hardware checksum (skb->csum)
               CHECKSUM_UNNECESSARY -> checksum level (skb->csum_level)
               otherwise -> 0

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 net/core/filter.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/net/core/filter.c b/net/core/filter.c
index b446aa8be5c3..71d58ea53512 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -12546,6 +12546,36 @@ __bpf_kfunc int bpf_xdp_pull_data(struct xdp_md *x, u32 len)
 	return 0;
 }
 
+/**
+ * bpf_skb_rx_checksum() - Read skb RX checksum info.
+ * @skb_: socket buffer to read from
+ * @ip_summed: return value for skb->ip_summed
+ * @csum_meta: checksum metadata
+ *
+ * Reads the checksum-related fields from a socket buffer. For
+ * %CHECKSUM_COMPLETE, csum_meta reports the hardware checksum value.
+ * For %CHECKSUM_UNNECESSARY, csum_meta reports the checksum level.
+ * For %CHECKSUM_NONE, csum_meta is zero.
+ *
+ * Return:
+ * * %0 - success
+ */
+__bpf_kfunc int bpf_skb_rx_checksum(struct __sk_buff *skb_, u32 *ip_summed,
+				    u32 *csum_meta)
+{
+	struct sk_buff *skb = (struct sk_buff *)skb_;
+
+	*ip_summed = skb->ip_summed;
+	if (skb->ip_summed == CHECKSUM_COMPLETE)
+		*csum_meta = skb->csum;
+	else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+		*csum_meta = skb->csum_level;
+	else
+		*csum_meta = 0;
+
+	return 0;
+}
+
 __bpf_kfunc_end_defs();
 
 int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
@@ -12565,6 +12595,7 @@ int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
 
 BTF_KFUNCS_START(bpf_kfunc_check_set_skb)
 BTF_ID_FLAGS(func, bpf_dynptr_from_skb)
+BTF_ID_FLAGS(func, bpf_skb_rx_checksum)
 BTF_KFUNCS_END(bpf_kfunc_check_set_skb)
 
 BTF_KFUNCS_START(bpf_kfunc_check_set_skb_meta)

-- 
2.55.0


^ permalink raw reply related

* [PATCH bpf-next v5 5/8] selftests/bpf: add bpf_xdp_metadata_rx_checksum support to xdp_hw_metadat prog
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Aleksandr Loktionov, Lorenzo Bianconi
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-0-623d5c0d0ab7@kernel.org>

Introduce the capability to dump HW rx checksum in xdp_hw_metadata
program via bpf_xdp_metadata_rx_checksum() kfunc.

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../testing/selftests/bpf/progs/xdp_hw_metadata.c  |  7 +++++
 tools/testing/selftests/bpf/xdp_hw_metadata.c      | 31 ++++++++++++++++++++++
 tools/testing/selftests/bpf/xdp_metadata.h         | 12 ++++++---
 3 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/bpf/progs/xdp_hw_metadata.c b/tools/testing/selftests/bpf/progs/xdp_hw_metadata.c
index 330ece2eabdb..5eeadb7e27cf 100644
--- a/tools/testing/selftests/bpf/progs/xdp_hw_metadata.c
+++ b/tools/testing/selftests/bpf/progs/xdp_hw_metadata.c
@@ -110,6 +110,13 @@ int rx(struct xdp_md *ctx)
 	else
 		meta->hint_valid |= XDP_META_FIELD_VLAN_TAG;
 
+	err = bpf_xdp_metadata_rx_checksum(ctx, &meta->ip_summed,
+					   &meta->cksum, &meta->cksum_level);
+	if (err)
+		meta->rx_cksum_err = err;
+	else
+		meta->hint_valid |= XDP_META_FIELD_CHECKSUM;
+
 	__sync_add_and_fetch(&pkts_redir, 1);
 	return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
 }
diff --git a/tools/testing/selftests/bpf/xdp_hw_metadata.c b/tools/testing/selftests/bpf/xdp_hw_metadata.c
index 6db3b5555a22..c63a70a54075 100644
--- a/tools/testing/selftests/bpf/xdp_hw_metadata.c
+++ b/tools/testing/selftests/bpf/xdp_hw_metadata.c
@@ -8,6 +8,7 @@
  * - Metadata verified:
  *   - rx_timestamp
  *   - rx_hash
+ *   - rx_checksum
  *
  * TX:
  * - UDP 9091 packets trigger TX reply
@@ -219,6 +220,30 @@ static void print_vlan_tci(__u16 tag)
 	printf("PCP=%u, DEI=%d, VID=0x%X\n", pcp, dei, vlan_id);
 }
 
+static void print_rx_cksum(__u8 ip_summed, __u32 cksum, __u8 cksum_level)
+{
+	const char *cksum_str;
+
+	switch (ip_summed) {
+	case XDP_CHECKSUM_COMPLETE | XDP_CHECKSUM_UNNECESSARY:
+		cksum_str = "CHECKSUM_COMPLETE,CHECKSUM_UNNECESSARY";
+		break;
+	case XDP_CHECKSUM_UNNECESSARY:
+		cksum_str = "CHECKSUM_UNNECESSARY";
+		break;
+	case XDP_CHECKSUM_COMPLETE:
+		cksum_str = "CHECKSUM_COMPLETE";
+		break;
+	case XDP_CHECKSUM_NONE:
+	default:
+		cksum_str = "CHECKSUM_NONE";
+		break;
+	}
+
+	printf("rx-cksum: %s, csum=0x%x, cksum_level=0x%x\n",
+	       cksum_str, cksum, cksum_level);
+}
+
 static void verify_xdp_metadata(void *data, clockid_t clock_id)
 {
 	struct xdp_meta *meta;
@@ -254,6 +279,12 @@ static void verify_xdp_metadata(void *data, clockid_t clock_id)
 		printf("No rx_vlan_tci or rx_vlan_proto, err=%d\n",
 		       meta->rx_vlan_tag_err);
 	}
+
+	if (meta->hint_valid & XDP_META_FIELD_CHECKSUM)
+		print_rx_cksum(meta->ip_summed, meta->cksum,
+			       meta->cksum_level);
+	else
+		printf("No rx_cksum, err=%d\n", meta->rx_cksum_err);
 }
 
 static void verify_skb_metadata(int fd)
diff --git a/tools/testing/selftests/bpf/xdp_metadata.h b/tools/testing/selftests/bpf/xdp_metadata.h
index bca09b94af26..f864d4a8bd8c 100644
--- a/tools/testing/selftests/bpf/xdp_metadata.h
+++ b/tools/testing/selftests/bpf/xdp_metadata.h
@@ -28,6 +28,7 @@ enum xdp_meta_field {
 	XDP_META_FIELD_TS	= BIT(0),
 	XDP_META_FIELD_RSS	= BIT(1),
 	XDP_META_FIELD_VLAN_TAG	= BIT(2),
+	XDP_META_FIELD_CHECKSUM = BIT(3),
 };
 
 #define XDP_CHECKSUM_NONE		BIT(0)
@@ -52,10 +53,13 @@ struct xdp_meta {
 		};
 		__s32 rx_vlan_tag_err;
 	};
-	struct {
-		__u32 ip_summed;
-		__u32 cksum;
-		__u8 cksum_level;
+	union {
+		struct {
+			__u32 ip_summed;
+			__u32 cksum;
+			__u8 cksum_level;
+		};
+		__s32 rx_cksum_err;
 	};
 	enum xdp_meta_field hint_valid;
 };

-- 
2.55.0


^ permalink raw reply related

* [PATCH bpf-next v5 4/8] selftests/bpf: add selftest support for bpf_xdp_metadata_rx_checksum
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Aleksandr Loktionov, Lorenzo Bianconi
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-0-623d5c0d0ab7@kernel.org>

Introduce dedicated selftest for bpf_xdp_metadata_rx_checksum kfunc to
bpf selftest framework.

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 tools/testing/selftests/bpf/prog_tests/xdp_metadata.c | 9 +++++++++
 tools/testing/selftests/bpf/progs/xdp_metadata.c      | 2 ++
 tools/testing/selftests/bpf/xdp_metadata.h            | 9 +++++++++
 3 files changed, 20 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c b/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
index 5c31054ad4a4..91de61c822f5 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
@@ -310,6 +310,15 @@ static int verify_xsk_metadata(struct xsk *xsk, bool sent_from_af_xdp)
 	if (!ASSERT_NEQ(meta->rx_hash, 0, "rx_hash"))
 		return -1;
 
+	if (!ASSERT_EQ(meta->ip_summed, XDP_CHECKSUM_NONE, "rx_ip_summed"))
+		return -1;
+
+	if (!ASSERT_EQ(meta->cksum, 0, "rx_cksum"))
+		return -1;
+
+	if (!ASSERT_EQ(meta->cksum_level, 0, "rx_cksum_level"))
+		return -1;
+
 	if (!sent_from_af_xdp) {
 		if (!ASSERT_NEQ(meta->rx_hash_type & XDP_RSS_TYPE_L4, 0, "rx_hash_type"))
 			return -1;
diff --git a/tools/testing/selftests/bpf/progs/xdp_metadata.c b/tools/testing/selftests/bpf/progs/xdp_metadata.c
index 09bb8a038d52..af1e19d48d67 100644
--- a/tools/testing/selftests/bpf/progs/xdp_metadata.c
+++ b/tools/testing/selftests/bpf/progs/xdp_metadata.c
@@ -98,6 +98,8 @@ int rx(struct xdp_md *ctx)
 	bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash, &meta->rx_hash_type);
 	bpf_xdp_metadata_rx_vlan_tag(ctx, &meta->rx_vlan_proto,
 				     &meta->rx_vlan_tci);
+	bpf_xdp_metadata_rx_checksum(ctx, &meta->ip_summed, &meta->cksum,
+				     &meta->cksum_level);
 
 	return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
 }
diff --git a/tools/testing/selftests/bpf/xdp_metadata.h b/tools/testing/selftests/bpf/xdp_metadata.h
index 87318ad1117a..bca09b94af26 100644
--- a/tools/testing/selftests/bpf/xdp_metadata.h
+++ b/tools/testing/selftests/bpf/xdp_metadata.h
@@ -30,6 +30,10 @@ enum xdp_meta_field {
 	XDP_META_FIELD_VLAN_TAG	= BIT(2),
 };
 
+#define XDP_CHECKSUM_NONE		BIT(0)
+#define XDP_CHECKSUM_UNNECESSARY	BIT(1)
+#define XDP_CHECKSUM_COMPLETE		BIT(2)
+
 struct xdp_meta {
 	union {
 		__u64 rx_timestamp;
@@ -48,5 +52,10 @@ struct xdp_meta {
 		};
 		__s32 rx_vlan_tag_err;
 	};
+	struct {
+		__u32 ip_summed;
+		__u32 cksum;
+		__u8 cksum_level;
+	};
 	enum xdp_meta_field hint_valid;
 };

-- 
2.55.0


^ permalink raw reply related

* [PATCH bpf-next v5 3/8] net: ice: add xmo_rx_checksum callback
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Aleksandr Loktionov, Lorenzo Bianconi
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-0-623d5c0d0ab7@kernel.org>

Implement xmo_rx_checksum callback in ice driver to report RX checksum
result to the eBPF program bounded to the NIC.
Introduce ice_get_rx_csum utility routine in order to make the rx checksum
code reusable from ice_rx_csum()

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/ethernet/intel/ice/ice_txrx_lib.c | 123 +++++++++++++++++---------
 1 file changed, 81 insertions(+), 42 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
index e695a664e53d..3aa82ff03d9e 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
@@ -78,69 +78,48 @@ ice_rx_hash_to_skb(const struct ice_rx_ring *rx_ring,
 		libeth_rx_pt_set_hash(skb, hash, decoded);
 }
 
-/**
- * ice_rx_gcs - Set generic checksum in skb
- * @skb: skb currently being received and modified
- * @rx_desc: receive descriptor
- */
-static void ice_rx_gcs(struct sk_buff *skb,
-		       const union ice_32b_rx_flex_desc *rx_desc)
-{
-	const struct ice_32b_rx_flex_desc_nic *desc;
-	u16 csum;
-
-	desc = (struct ice_32b_rx_flex_desc_nic *)rx_desc;
-	skb->ip_summed = CHECKSUM_COMPLETE;
-	csum = (__force u16)desc->raw_csum;
-	skb->csum = csum_unfold((__force __sum16)swab16(csum));
-}
-
-/**
- * ice_rx_csum - Indicate in skb if checksum is good
- * @ring: the ring we care about
- * @skb: skb currently being received and modified
- * @rx_desc: the receive descriptor
- * @ptype: the packet type decoded by hardware
- *
- * skb->protocol must be set before this function is called
- */
 static void
-ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb,
-	    union ice_32b_rx_flex_desc *rx_desc, u16 ptype)
+ice_get_rx_csum(const union ice_32b_rx_flex_desc *rx_desc, u16 ptype,
+		struct ice_rx_ring *ring, enum xdp_checksum *ip_summed,
+		u32 *cksum, u8 *cksum_level)
 {
-	struct libeth_rx_pt decoded;
+	struct libeth_rx_pt decoded = libie_rx_pt_parse(ptype);
 	u16 rx_status0, rx_status1;
 	bool ipv4, ipv6;
 
-	/* Start with CHECKSUM_NONE and by default csum_level = 0 */
-	skb->ip_summed = CHECKSUM_NONE;
-
-	decoded = libie_rx_pt_parse(ptype);
 	if (!libeth_rx_pt_has_checksum(ring->netdev, decoded))
-		return;
+		goto checksum_none;
 
 	rx_status0 = le16_to_cpu(rx_desc->wb.status_error0);
 	rx_status1 = le16_to_cpu(rx_desc->wb.status_error1);
-
 	if ((ring->flags & ICE_RX_FLAGS_RING_GCS) &&
 	    rx_desc->wb.rxdid == ICE_RXDID_FLEX_NIC &&
 	    (decoded.inner_prot == LIBETH_RX_PT_INNER_TCP ||
 	     decoded.inner_prot == LIBETH_RX_PT_INNER_UDP ||
 	     decoded.inner_prot == LIBETH_RX_PT_INNER_ICMP)) {
-		ice_rx_gcs(skb, rx_desc);
+		const struct ice_32b_rx_flex_desc_nic *desc;
+		__wsum wcsum;
+		u16 csum;
+
+		desc = (struct ice_32b_rx_flex_desc_nic *)rx_desc;
+		*ip_summed = XDP_CHECKSUM_COMPLETE;
+		csum = (__force u16)desc->raw_csum;
+		wcsum = csum_unfold((__force __sum16)swab16(csum));
+		*cksum = (__force u32)wcsum;
+		*cksum_level = 0;
 		return;
 	}
 
 	/* check if HW has decoded the packet and checksum */
 	if (!(rx_status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L3L4P_S)))
-		return;
+		goto checksum_none;
 
 	ipv4 = libeth_rx_pt_get_ip_ver(decoded) == LIBETH_RX_PT_OUTER_IPV4;
 	ipv6 = libeth_rx_pt_get_ip_ver(decoded) == LIBETH_RX_PT_OUTER_IPV6;
 
 	if (ipv4 && (rx_status0 & (BIT(ICE_RX_FLEX_DESC_STATUS0_XSUM_EIPE_S)))) {
 		ring->vsi->back->hw_rx_eipe_error++;
-		return;
+		goto checksum_none;
 	}
 
 	if (ipv4 && (rx_status0 & (BIT(ICE_RX_FLEX_DESC_STATUS0_XSUM_IPE_S))))
@@ -164,14 +143,51 @@ ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb,
 	 * we need to bump the checksum level by 1 to reflect the fact that
 	 * we are indicating we validated the inner checksum.
 	 */
-	if (decoded.tunnel_type >= LIBETH_RX_PT_TUNNEL_IP_GRENAT)
-		skb->csum_level = 1;
-
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	*cksum_level = decoded.tunnel_type >= LIBETH_RX_PT_TUNNEL_IP_GRENAT;
+	*ip_summed = XDP_CHECKSUM_UNNECESSARY;
+	*cksum = 0;
 	return;
 
 checksum_fail:
 	ring->vsi->back->hw_csum_rx_error++;
+checksum_none:
+	*ip_summed = XDP_CHECKSUM_NONE;
+	*cksum_level = 0;
+	*cksum = 0;
+}
+
+/**
+ * ice_rx_csum - Indicate in skb if checksum is good
+ * @ring: the ring we care about
+ * @skb: skb currently being received and modified
+ * @rx_desc: the receive descriptor
+ * @ptype: the packet type decoded by hardware
+ *
+ * skb->protocol must be set before this function is called
+ */
+static void
+ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb,
+	    union ice_32b_rx_flex_desc *rx_desc, u16 ptype)
+{
+	enum xdp_checksum ip_summed;
+	u8 cksum_level;
+	u32 cksum;
+
+	ice_get_rx_csum(rx_desc, ptype, ring, &ip_summed, &cksum,
+			&cksum_level);
+	switch (ip_summed) {
+	case XDP_CHECKSUM_UNNECESSARY:
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->csum_level = cksum_level;
+		break;
+	case XDP_CHECKSUM_COMPLETE:
+		skb->ip_summed = CHECKSUM_COMPLETE;
+		skb->csum = (__force __wsum)cksum;
+		break;
+	default:
+		skb->ip_summed = CHECKSUM_NONE;
+		break;
+	}
 }
 
 /**
@@ -566,6 +582,28 @@ static int ice_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
 	return 0;
 }
 
+/**
+ * ice_xdp_rx_checksum - RX checksum XDP hint handler
+ * @ctx: XDP buff pointer
+ * @ip_summed: RX checksum result destination address
+ * @cksum: RX checksum value destination address
+ * @cksum_level: RX checksum level value destination address
+ */
+static int ice_xdp_rx_checksum(const struct xdp_md *ctx,
+			       enum xdp_checksum *ip_summed,
+			       u32 *cksum, u8 *cksum_level)
+{
+	const struct libeth_xdp_buff *xdp_ext = (void *)ctx;
+	const union ice_32b_rx_flex_desc *rx_desc = xdp_ext->desc;
+	struct ice_rx_ring *ring;
+
+	ring = libeth_xdp_buff_to_rq(xdp_ext, typeof(*ring), xdp_rxq);
+	ice_get_rx_csum(rx_desc, ice_get_ptype(rx_desc), ring, ip_summed,
+			cksum, cksum_level);
+
+	return 0;
+}
+
 /**
  * ice_xdp_rx_vlan_tag - VLAN tag XDP hint handler
  * @ctx: XDP buff pointer
@@ -598,4 +636,5 @@ const struct xdp_metadata_ops ice_xdp_md_ops = {
 	.xmo_rx_timestamp		= ice_xdp_rx_hw_ts,
 	.xmo_rx_hash			= ice_xdp_rx_hash,
 	.xmo_rx_vlan_tag		= ice_xdp_rx_vlan_tag,
+	.xmo_rx_checksum		= ice_xdp_rx_checksum,
 };

-- 
2.55.0


^ permalink raw reply related

* [PATCH bpf-next v5 2/8] net: veth: add xmo_rx_checksum callback to veth driver
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Aleksandr Loktionov, Lorenzo Bianconi
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-0-623d5c0d0ab7@kernel.org>

Implement xmo_rx_checksum callback in veth driver to report RX checksum
result to the eBPF program bounded to the veth device.

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/veth.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 8170bf33ccf9..dbf30089581c 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1701,6 +1701,37 @@ static int veth_xdp_rx_vlan_tag(const struct xdp_md *ctx, __be16 *vlan_proto,
 	return err;
 }
 
+static int veth_xdp_rx_checksum(const struct xdp_md *ctx,
+				enum xdp_checksum *ip_summed,
+				u32 *cksum, u8 *cksum_level)
+{
+	const struct veth_xdp_buff *_ctx = (void *)ctx;
+	const struct sk_buff *skb = _ctx->skb;
+
+	if (!skb)
+		return -ENODATA;
+
+	switch (skb->ip_summed) {
+	case CHECKSUM_COMPLETE:
+		*ip_summed = XDP_CHECKSUM_COMPLETE;
+		*cksum = skb->csum;
+		*cksum_level = 0;
+		break;
+	case CHECKSUM_UNNECESSARY:
+		*ip_summed = XDP_CHECKSUM_UNNECESSARY;
+		*cksum_level = skb->csum_level;
+		*cksum = 0;
+		break;
+	default:
+		*ip_summed = XDP_CHECKSUM_NONE;
+		*cksum_level = 0;
+		*cksum = 0;
+		break;
+	}
+
+	return 0;
+}
+
 static const struct net_device_ops veth_netdev_ops = {
 	.ndo_init            = veth_dev_init,
 	.ndo_open            = veth_open,
@@ -1726,6 +1757,7 @@ static const struct xdp_metadata_ops veth_xdp_metadata_ops = {
 	.xmo_rx_timestamp		= veth_xdp_rx_timestamp,
 	.xmo_rx_hash			= veth_xdp_rx_hash,
 	.xmo_rx_vlan_tag		= veth_xdp_rx_vlan_tag,
+	.xmo_rx_checksum		= veth_xdp_rx_checksum,
 };
 
 #define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM | \

-- 
2.55.0


^ permalink raw reply related

* [PATCH bpf-next v5 1/8] netlink: specs: add XDP RX checksum capability to XDP metadata specs
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Aleksandr Loktionov, Lorenzo Bianconi
In-Reply-To: <20260715-bpf-xdp-meta-rxcksum-v5-0-623d5c0d0ab7@kernel.org>

Introduce XDP RX checksum capability to XDP metadata specs. XDP RX
checksum will be use by devices capable of exposing receive checksum
result via bpf_xdp_metadata_rx_checksum().
Moreover, introduce xmo_rx_checksum netdev callback in order to allow
the eBPF program bound to the device to retrieve the RX checksum result
computed by the hw NIC and reported via DMA descriptors.

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 Documentation/netlink/specs/netdev.yaml      |  5 +++++
 Documentation/networking/xdp-rx-metadata.rst |  3 +++
 include/net/xdp.h                            | 13 +++++++++++
 include/uapi/linux/netdev.h                  |  3 +++
 net/core/xdp.c                               | 32 ++++++++++++++++++++++++++++
 tools/include/uapi/linux/netdev.h            |  3 +++
 6 files changed, 59 insertions(+)

diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml
index 5f143da7458c..6d0d90d3a614 100644
--- a/Documentation/netlink/specs/netdev.yaml
+++ b/Documentation/netlink/specs/netdev.yaml
@@ -61,6 +61,11 @@ definitions:
         doc: |
           Device is capable of exposing receive packet VLAN tag via
           bpf_xdp_metadata_rx_vlan_tag().
+      -
+        name: checksum
+        doc: |
+          Device is capable of exposing receive checksum result via
+          bpf_xdp_metadata_rx_checksum().
   -
     type: flags
     name: xsk-flags
diff --git a/Documentation/networking/xdp-rx-metadata.rst b/Documentation/networking/xdp-rx-metadata.rst
index efdf5eeb49e7..93918b3769a3 100644
--- a/Documentation/networking/xdp-rx-metadata.rst
+++ b/Documentation/networking/xdp-rx-metadata.rst
@@ -28,6 +28,9 @@ metadata is supported, this set will grow:
 .. kernel-doc:: net/core/xdp.c
    :identifiers: bpf_xdp_metadata_rx_vlan_tag
 
+.. kernel-doc:: net/core/xdp.c
+   :identifiers: bpf_xdp_metadata_rx_checksum
+
 An XDP program can use these kfuncs to read the metadata into stack
 variables for its own consumption. Or, to pass the metadata on to other
 consumers, an XDP program can store it into the metadata area carried
diff --git a/include/net/xdp.h b/include/net/xdp.h
index aa742f413c35..d95e126f2426 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -586,6 +586,10 @@ void xdp_attachment_setup(struct xdp_attachment_info *info,
 			   NETDEV_XDP_RX_METADATA_VLAN_TAG, \
 			   bpf_xdp_metadata_rx_vlan_tag, \
 			   xmo_rx_vlan_tag) \
+	XDP_METADATA_KFUNC(XDP_METADATA_KFUNC_RX_CHECKSUM, \
+			   NETDEV_XDP_RX_METADATA_CHECKSUM, \
+			   bpf_xdp_metadata_rx_checksum, \
+			   xmo_rx_checksum)
 
 enum xdp_rx_metadata {
 #define XDP_METADATA_KFUNC(name, _, __, ___) name,
@@ -643,12 +647,21 @@ enum xdp_rss_hash_type {
 	XDP_RSS_TYPE_L4_IPV6_SCTP_EX = XDP_RSS_TYPE_L4_IPV6_SCTP | XDP_RSS_L3_DYNHDR,
 };
 
+enum xdp_checksum {
+	XDP_CHECKSUM_NONE		= BIT(CHECKSUM_NONE),
+	XDP_CHECKSUM_UNNECESSARY	= BIT(CHECKSUM_UNNECESSARY),
+	XDP_CHECKSUM_COMPLETE		= BIT(CHECKSUM_COMPLETE),
+};
+
 struct xdp_metadata_ops {
 	int	(*xmo_rx_timestamp)(const struct xdp_md *ctx, u64 *timestamp);
 	int	(*xmo_rx_hash)(const struct xdp_md *ctx, u32 *hash,
 			       enum xdp_rss_hash_type *rss_type);
 	int	(*xmo_rx_vlan_tag)(const struct xdp_md *ctx, __be16 *vlan_proto,
 				   u16 *vlan_tci);
+	int	(*xmo_rx_checksum)(const struct xdp_md *ctx,
+				   enum xdp_checksum *ip_summed,
+				   u32 *cksum, u8 *cksum_level);
 };
 
 #ifdef CONFIG_NET
diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h
index 2f3ab75e8cc0..f8caade93c8c 100644
--- a/include/uapi/linux/netdev.h
+++ b/include/uapi/linux/netdev.h
@@ -47,11 +47,14 @@ enum netdev_xdp_act {
  *   hash via bpf_xdp_metadata_rx_hash().
  * @NETDEV_XDP_RX_METADATA_VLAN_TAG: Device is capable of exposing receive
  *   packet VLAN tag via bpf_xdp_metadata_rx_vlan_tag().
+ * @NETDEV_XDP_RX_METADATA_CHECKSUM: Device is capable of exposing receive
+ *   checksum result via bpf_xdp_metadata_rx_checksum().
  */
 enum netdev_xdp_rx_metadata {
 	NETDEV_XDP_RX_METADATA_TIMESTAMP = 1,
 	NETDEV_XDP_RX_METADATA_HASH = 2,
 	NETDEV_XDP_RX_METADATA_VLAN_TAG = 4,
+	NETDEV_XDP_RX_METADATA_CHECKSUM = 8,
 };
 
 /**
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 9890a30584ba..9bcaa423ad17 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -961,6 +961,38 @@ __bpf_kfunc int bpf_xdp_metadata_rx_vlan_tag(const struct xdp_md *ctx,
 	return -EOPNOTSUPP;
 }
 
+/**
+ * bpf_xdp_metadata_rx_checksum - Read XDP frame RX checksum.
+ * @ctx: XDP context pointer.
+ * @ip_summed: Return value pointer to a bitmask indicating available checksums.
+ * @cksum: Return value pointer indicating the hw checksum value.
+ * @cksum_level: Return value pointer indicating the checksum level result.
+ *
+ * In case of success, ``ip_summed`` is set to the RX checksum result. Possible
+ * values are:
+ * ``XDP_CHECKSUM_NONE``
+ * ``XDP_CHECKSUM_UNNECESSARY``
+ * ``XDP_CHECKSUM_COMPLETE``
+ * ``XDP_CHECKSUM_COMPLETE`` | ``XDP_CHECKSUM_UNNECESSARY``
+ *
+ * In case of success, ``cksum`` contains the checksum value calculated by the
+ * NIC. ``cksum`` is valid only if ``XDP_CHECKSUM_COMPLETE`` is set in
+ * ``ip_summed``. ``cksum_level`` contains the checksum level reported by the
+ * hw. ``cksum_level`` can be considered valid only if
+ * ``XDP_CHECKSUM_UNNECESSARY`` is set in ``ip_summed``.
+ *
+ * Return:
+ * * Returns 0 on success or ``-errno`` on error.
+ * * ``-EOPNOTSUPP`` : means device driver does not implement kfunc
+ * * ``-ENODATA``    : means no RX-checksum available for this frame
+ */
+__bpf_kfunc int bpf_xdp_metadata_rx_checksum(const struct xdp_md *ctx,
+					     enum xdp_checksum *ip_summed,
+					     u32 *cksum, u8 *cksum_level)
+{
+	return -EOPNOTSUPP;
+}
+
 __bpf_kfunc_end_defs();
 
 BTF_KFUNCS_START(xdp_metadata_kfunc_ids)
diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h
index 2f3ab75e8cc0..f8caade93c8c 100644
--- a/tools/include/uapi/linux/netdev.h
+++ b/tools/include/uapi/linux/netdev.h
@@ -47,11 +47,14 @@ enum netdev_xdp_act {
  *   hash via bpf_xdp_metadata_rx_hash().
  * @NETDEV_XDP_RX_METADATA_VLAN_TAG: Device is capable of exposing receive
  *   packet VLAN tag via bpf_xdp_metadata_rx_vlan_tag().
+ * @NETDEV_XDP_RX_METADATA_CHECKSUM: Device is capable of exposing receive
+ *   checksum result via bpf_xdp_metadata_rx_checksum().
  */
 enum netdev_xdp_rx_metadata {
 	NETDEV_XDP_RX_METADATA_TIMESTAMP = 1,
 	NETDEV_XDP_RX_METADATA_HASH = 2,
 	NETDEV_XDP_RX_METADATA_VLAN_TAG = 4,
+	NETDEV_XDP_RX_METADATA_CHECKSUM = 8,
 };
 
 /**

-- 
2.55.0


^ permalink raw reply related

* [PATCH bpf-next v5 0/8] Add the the capability to load HW RX checksum in eBPF programs
From: Lorenzo Bianconi @ 2026-07-15 21:39 UTC (permalink / raw)
  To: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrew Lunn, Tony Nguyen, Przemek Kitszel, Alexander Lobakin,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Maciej Fijalkowski, Jonathan Corbet, Shuah Khan,
	Kumar Kartikeya Dwivedi, Emil Tsalapatis
  Cc: Vladimir Vdovin, Jakub Sitnicki, netdev, bpf, intel-wired-lan,
	linux-kselftest, linux-doc, Aleksandr Loktionov, Lorenzo Bianconi

Introduce bpf_xdp_metadata_rx_checksum() kfunc in order to load the HW
RX checksum results in the eBPF program binded to the NIC.
Implement xmo_rx_checksum callback for veth and ice drivers.

If the hardware detects a wrong/failed checksum, it will report
CHECKSUM_NONE in the packet metadata. Moreover, CHECKSUM_NONE will be
returned even if the NIC can't parse the packet (e.g. if it does not
support a specific protocol). A possible use case for
bpf_xdp_metadata_rx_checksum() would be to implement a XDP DDoS
application [1] combining the info from bpf_xdp_metadata_rx_checksum()
and bpf_xdp_metadata_rx_hash() kfuncs in order to filter packets with a
wrong/failed checksum.

[1] https://blog.cloudflare.com/unimog-cloudflares-edge-load-balancer/

---
Changes in v5:
- Add new kfunc to Documentation/networking/xdp-rx-metadata.rst
  documentation
- Introduce bpf_skb_rx_checksum kfunc and related selftest.
- Introduce selftest to check the driver invalidates the rx checksum if
  running in XDP mode.

Changes in v4:
- Report cusm and csum_level separately and convert ip_summed to a
  bitmask in bpf_xdp_metadata_rx_hash()
- Fix endianness issue in bpf selftests
- Add a comment about the driver expected behaviour if the the NIC reports
  CHECKSUM_UNNECESSARY or CHECKSUM_COMPLETE and the eBPF program modifes
  the packet
- Introduce bpf_get_skb_cksum kfunc and related selftest to load the
  checksum result to the SCHED_CLS eBPF program attached to the qdisc.
- Link to v3: https://lore.kernel.org/r/20260217-bpf-xdp-meta-rxcksum-v3-0-30024c50ba71@kernel.org

Changes in v3:
- Remoe leftover assignment from v2 in veth_xdp_rx_checksum()
- Fix typos
- Fix commit logs
- Link to v2: https://lore.kernel.org/r/20260213-bpf-xdp-meta-rxcksum-v2-0-a82c4802afbe@kernel.org

Changes in v2:
- Remove XDP_CHECKSUM_PARTIAL definition
- Improve veth_xdp_rx_checksum() callback
- Fix uninitialized case for cksum_meta in ice_get_rx_csum()
- Fix sparse warnings in ice driver
- Fix typos
- Link to v1: https://lore.kernel.org/r/20260210-bpf-xdp-meta-rxcksum-v1-0-e5d55caa0541@kernel.org

Changes in v1:
- Rebase on top of bpf-next
- Test ice driver using xdp_hw_metadata tool available in the bpf
  kernel selftest
- Improve cover letter with an use-case for
  bpf_xdp_metadata_rx_checksum()
- Link to RFC v2: https://lore.kernel.org/r/20250925-bpf-xdp-meta-rxcksum-v2-0-6b3fe987ce91@kernel.org

Changes in RFC v2:
- Squash patch 1/6 and 2/6
- Introduce enum xdp_checksum definitions
- Rework ice support to reuse ice_rx_csum codebase

---
Lorenzo Bianconi (8):
      netlink: specs: add XDP RX checksum capability to XDP metadata specs
      net: veth: add xmo_rx_checksum callback to veth driver
      net: ice: add xmo_rx_checksum callback
      selftests/bpf: add selftest support for bpf_xdp_metadata_rx_checksum
      selftests/bpf: add bpf_xdp_metadata_rx_checksum support to xdp_hw_metadat prog
      net: add bpf_skb_rx_checksum kfunc to read skb checksum metadata
      selftests/bpf: Add test for bpf_skb_rx_checksum kfunc
      selftests: net: add test for XDP_PASS skb checksum invalidation

 Documentation/netlink/specs/netdev.yaml            |   5 +
 Documentation/networking/xdp-rx-metadata.rst       |   8 ++
 drivers/net/ethernet/intel/ice/ice_txrx_lib.c      | 123 ++++++++++++++-------
 drivers/net/veth.c                                 |  32 ++++++
 include/net/xdp.h                                  |  13 +++
 include/uapi/linux/netdev.h                        |   3 +
 net/core/filter.c                                  |  31 ++++++
 net/core/xdp.c                                     |  32 ++++++
 tools/include/uapi/linux/netdev.h                  |   3 +
 tools/testing/selftests/bpf/bpf_kfuncs.h           |   8 ++
 .../selftests/bpf/prog_tests/skb_rx_checksum.c     |  50 +++++++++
 .../selftests/bpf/prog_tests/xdp_metadata.c        |   9 ++
 .../testing/selftests/bpf/progs/skb_rx_checksum.c  |  33 ++++++
 .../testing/selftests/bpf/progs/xdp_hw_metadata.c  |   7 ++
 tools/testing/selftests/bpf/progs/xdp_metadata.c   |   2 +
 tools/testing/selftests/bpf/skb_rx_checksum.h      |   8 ++
 tools/testing/selftests/bpf/xdp_hw_metadata.c      |  31 ++++++
 tools/testing/selftests/bpf/xdp_metadata.h         |  13 +++
 .../selftests/drivers/net/hw/xdp_metadata.py       |  55 ++++++++-
 .../selftests/net/lib/skb_metadata_csum.bpf.c      |  73 ++++++++++++
 20 files changed, 496 insertions(+), 43 deletions(-)
---
base-commit: f6f3b36c15ed44de1fbb44e645e4fae8c4a4453e
change-id: 20250925-bpf-xdp-meta-rxcksum-900685e2909d

Best regards,
-- 
Lorenzo Bianconi <lorenzo@kernel.org>


^ permalink raw reply

* Re: [PATCH v9 0/8] mm/hmm: Add mmap lock-drop support for userfaultfd-backed mappings
From: Andrew Morton @ 2026-07-15 21:17 UTC (permalink / raw)
  To: Stanislav Kinsburskii
  Cc: airlied, akhilesh, corbet, dakr, david, decui, haiyangz, jgg,
	kees, kys, leon, liam, lizhi.hou, ljs, longli, lyude,
	maarten.lankhorst, mamin506, mhocko, mripard, nouveau, ogabbay,
	oleg, rppt, shuah, simona, skhan, surenb, tzimmermann, vbabka,
	wei.liu, dri-devel, intel-xe, linux-mm, linux-doc, linux-hyperv,
	linux-kernel, linux-kselftest, linux-rdma
In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii>

On Wed, 15 Jul 2026 11:15:50 -0700 Stanislav Kinsburskii <skinsburskii@gmail.com> wrote:

> This series extends the HMM framework to support userfaultfd-backed memory
> by allowing the mmap read lock to be dropped during hmm_range_fault().

Thanks, updated.

> Changes in v9:
> 
>   - Folded the fixups into the full 8-patch series instead of sending a
>     separate fixup series.
>   - Clarified that the HMM timeout bounds repeated HMM/mmu-notifier retry
>     attempts, with the helper refreshing range->notifier_seq internally.
>   - Kept nouveau’s explicit outer deadline because its retry loop runs in a GPU
>     fault worker and cannot rely on fatal signals from the faulting process.
>   - Converted amdxdna, and GPU SVM callers to pass the shole timeout budget to
>     hmm_range_fault_unlocked_timeout().

These are all in your fixups for v8, so the v9 series made no
alteration to mm.git.


^ permalink raw reply

* [PATCH v5] arm64: errata: work around NVIDIA Olympus device store/load ordering
From: Shanker Donthineni @ 2026-07-15 20:48 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Vladimir Murzin
  Cc: Jason Gunthorpe, linux-arm-kernel, Mark Rutland, linux-kernel,
	linux-doc, Shanker Donthineni, Vikram Sethi, Jason Sequeira

On systems with NVIDIA Olympus cores, a Device-nGnR* load can be
observed by a peripheral before an older, non-overlapping Device-nGnR*
store to the same peripheral. This breaks the program-order guarantee
that software expects for Device-nGnR* accesses and can leave a
peripheral in an incorrect state.

The erratum can occur only when all of the following apply:

  - A PE executes a Device-nGnR* store followed by a younger
    Device-nGnR* load.
  - The store is not a store-release.
  - The accesses target the same peripheral and do not overlap in bytes.
  - There is at most one intervening Device-nGnR* store in program
    order, and there are no intervening Device-nGnR* loads.
  - There is no DSB or full DMB between the store and the load.
  - Specific microarchitectural and timing conditions occur.

Insert a DMB OSH immediately before each raw MMIO load on affected CPUs.
As a full barrier, DMB OSH orders the older Device store before the
younger Device load and prevents the erroneous observation.

Add the barrier directly to the __raw_read*() helpers, independently of
the existing device-load-acquire alternative. On affected CPUs this adds
one DMB OSH per raw MMIO load, including each load used by
memcpy_fromio(). On unaffected CPUs the alternative remains a NOP.

Co-developed-by: Vikram Sethi <vsethi@nvidia.com>
Signed-off-by: Vikram Sethi <vsethi@nvidia.com>
Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
Link: https://lore.kernel.org/all/akPQ8F3OgER621UP@willie-the-truck/
---
Changes since v4:
  - Reworked the workaround following Will Deacon's review: leave the raw
    MMIO write helpers unchanged and insert a DMB OSH before raw MMIO loads.
  - Use DMB OSH after hardware confirmation that it fixes T410-OLY-1027.
  - Dropped the separate memcpy_fromio() optimization patch because the
    benchmark showed no noticeable benefit over the per-load workaround.
  - Updated the cpucap, Kconfig help text, and commit messages for the
    load-side workaround.

Changes since v3:
  - Split the workaround into two patches: the erratum fix (1/2) and the
    arm64 memset_io()/memcpy_toio() block writers (2/2).
  - Reworked the raw MMIO write helpers to use a direct base-register
    str*/stlr* alternative sequence instead of a per-write static branch.
  - Covered the write-combining __iowrite{32,64}_copy() path by patching
    dgh() to dmb osh on affected CPUs, keeping the contiguous STR groups
    and the ordering barrier outside the copy loop; the single-element
    case now uses a plain str* as well.
  - Added arm64 memset_io()/memcpy_toio() so the byte/word block writers
    take one trailing dmb osh instead of a per-store store-release.
  - Updated the commit messages to describe the offset-addressing
    trade-off.

Changes since v2:
  - Reworked the raw MMIO write helpers so unaffected CPUs keep the
    existing offset-addressed STR sequence, while affected CPUs use the
    base-register STLR path.
  - Updated the commit message to match the code changes.
  - Rebased on top of the arm64 for-next/errata branch:
    https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=for-next/errata

Changes since v1:
  - Updated the commit message based on feedback from Vladimir Murzin.

---
 Documentation/arch/arm64/silicon-errata.rst |  2 ++
 arch/arm64/Kconfig                          | 22 +++++++++++++++++++++
 arch/arm64/include/asm/io.h                 | 16 ++++++++++++----
 arch/arm64/kernel/cpu_errata.c              |  8 ++++++++
 arch/arm64/tools/cpucaps                    |  1 +
 5 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index ad04d1cdc0f0..c4137f89acef 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -298,6 +298,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | NVIDIA         | Carmel Core     | N/A             | NVIDIA_CARMEL_CNP_ERRATUM   |
 +----------------+-----------------+-----------------+-----------------------------+
+| NVIDIA         | Olympus core    | T410-OLY-1027   | NVIDIA_OLYMPUS_1027_ERRATUM |
++----------------+-----------------+-----------------+-----------------------------+
 | NVIDIA         | Olympus core    | T410-OLY-1029   | ARM64_ERRATUM_4118414       |
 +----------------+-----------------+-----------------+-----------------------------+
 | NVIDIA         | T241 GICv3/4.x  | T241-FABRIC-4   | N/A                         |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 10c69474f276..73e3e68db161 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1363,6 +1363,28 @@ config NVIDIA_CARMEL_CNP_ERRATUM
 
 	  If unsure, say Y.
 
+config NVIDIA_OLYMPUS_1027_ERRATUM
+	bool "NVIDIA Olympus: device store/load ordering erratum"
+	default y
+	help
+	  This option adds an alternative code sequence to work around an
+	  NVIDIA Olympus core erratum where a Device-nGnR* store can be
+	  observed by a peripheral after a younger Device-nGnR* load to the
+	  same peripheral. This breaks the program order that drivers rely
+	  on for MMIO and can leave a device in an incorrect state.
+
+	  The workaround inserts a DMB OSH immediately before raw MMIO loads.
+	  The erratum cannot occur when a DMB that orders loads appears
+	  between the store and load, preventing the younger load from being
+	  observed before the older store.
+
+	  The alternatives framework patches in DMB OSH only when an affected
+	  CPU is detected. Other CPUs execute a NOP in its place. Disabling
+	  this option leaves the original MMIO read instruction stream
+	  unchanged.
+
+	  If unsure, say Y.
+
 config ROCKCHIP_ERRATUM_3568002
 	bool "Rockchip 3568002: GIC600 can not access physical addresses higher than 4GB"
 	default y
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 8cbd1e96fd50..6d6d54c1b74c 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -54,7 +54,9 @@ static __always_inline void __raw_writeq(u64 val, volatile void __iomem *addr)
 static __always_inline u8 __raw_readb(const volatile void __iomem *addr)
 {
 	u8 val;
-	asm volatile(ALTERNATIVE("ldrb %w0, [%1]",
+	asm volatile(ALTERNATIVE("nop", "dmb osh",
+				 ARM64_WORKAROUND_NVIDIA_OLYMPUS_1027)
+		     ALTERNATIVE("ldrb %w0, [%1]",
 				 "ldarb %w0, [%1]",
 				 ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
 		     : "=r" (val) : "r" (addr));
@@ -66,7 +68,9 @@ static __always_inline u16 __raw_readw(const volatile void __iomem *addr)
 {
 	u16 val;
 
-	asm volatile(ALTERNATIVE("ldrh %w0, [%1]",
+	asm volatile(ALTERNATIVE("nop", "dmb osh",
+				 ARM64_WORKAROUND_NVIDIA_OLYMPUS_1027)
+		     ALTERNATIVE("ldrh %w0, [%1]",
 				 "ldarh %w0, [%1]",
 				 ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
 		     : "=r" (val) : "r" (addr));
@@ -77,7 +81,9 @@ static __always_inline u16 __raw_readw(const volatile void __iomem *addr)
 static __always_inline u32 __raw_readl(const volatile void __iomem *addr)
 {
 	u32 val;
-	asm volatile(ALTERNATIVE("ldr %w0, [%1]",
+	asm volatile(ALTERNATIVE("nop", "dmb osh",
+				 ARM64_WORKAROUND_NVIDIA_OLYMPUS_1027)
+		     ALTERNATIVE("ldr %w0, [%1]",
 				 "ldar %w0, [%1]",
 				 ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
 		     : "=r" (val) : "r" (addr));
@@ -88,7 +94,9 @@ static __always_inline u32 __raw_readl(const volatile void __iomem *addr)
 static __always_inline u64 __raw_readq(const volatile void __iomem *addr)
 {
 	u64 val;
-	asm volatile(ALTERNATIVE("ldr %0, [%1]",
+	asm volatile(ALTERNATIVE("nop", "dmb osh",
+				 ARM64_WORKAROUND_NVIDIA_OLYMPUS_1027)
+		     ALTERNATIVE("ldr %0, [%1]",
 				 "ldar %0, [%1]",
 				 ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
 		     : "=r" (val) : "r" (addr));
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 4b0d5d932897..740ba3d51e30 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -839,6 +839,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
 	},
 #endif
+#ifdef CONFIG_NVIDIA_OLYMPUS_1027_ERRATUM
+	{
+		/* NVIDIA Olympus core */
+		.desc = "NVIDIA Olympus device store/load ordering erratum",
+		.capability = ARM64_WORKAROUND_NVIDIA_OLYMPUS_1027,
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
+	},
+#endif
 #ifdef CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
 	{
 		/*
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 811c2479e82d..8d919b6699f0 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -121,6 +121,7 @@ WORKAROUND_CAVIUM_TX2_219_TVM
 WORKAROUND_CLEAN_CACHE
 WORKAROUND_DEVICE_LOAD_ACQUIRE
 WORKAROUND_NVIDIA_CARMEL_CNP
+WORKAROUND_NVIDIA_OLYMPUS_1027
 WORKAROUND_PMUV3_IMPDEF_TRAPS
 WORKAROUND_QCOM_FALKOR_E1003
 WORKAROUND_QCOM_ORYON_CNTVOFF
-- 
2.54.0.windows.1

^ permalink raw reply related

* Re: [PATCH v2 0/3] tools/accounting: refactor delay fields and share format_timespec()
From: Andrew Morton @ 2026-07-15 19:59 UTC (permalink / raw)
  To: wang.yaxin
  Cc: fan.yu9, yang.yang29, corbet, linux-kernel, linux-doc, xu.xin16
In-Reply-To: <20260715124740929HC7tDDb2SK3kRxbuPruHd@zte.com.cn>

On Wed, 15 Jul 2026 12:47:40 +0800 (CST) <wang.yaxin@zte.com.cn> wrote:

> From: Wang Yaxin <wang.yaxin@zte.com.cn>
> 
> - Convert per-field delay members in struct task_info to an array indexed
>   by enum delay_type, eliminating offsetof() pointer arithmetic.
> 
> - Factor out a common format_timespec() implementation shared by getdelays
>   and delaytop, using strftime for cleaner timestamp formatting.
> 
> - Replace the complex sizeof/ULL/shift Y2038 guard with a direct narrowing
>   truncation check ((long long)time_sec != ts->tv_sec).
> 
> Change Log
> ==========
> v1->v2:
> Only update patch 2/3 according to the suggestion:
> https://sashiko.dev/#/patchset/20260711173112482SCQEM08VED2PT1pxUYOXk@zte.com.cn

Thanks.  Sashiko asked a new question:
	https://sashiko.dev/#/patchset/20260715124740929HC7tDDb2SK3kRxbuPruHd@zte.com.cn

^ permalink raw reply

* [PATCH v1 5/7] MIPS: BCM63XX: Remove one time use ephy_reset_gpio_flags
From: Andy Shevchenko @ 2026-07-15 18:46 UTC (permalink / raw)
  To: Andy Shevchenko, Bradford Love, linux-gpio, linux-doc,
	linux-kernel, linux-arm-kernel, linux-mips, linux-media
  Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Shuah Khan,
	Daniel Mack, Haojian Zhuang, Robert Jarzmik, Russell King,
	Hauke Mehrtens, Rafał Miłecki, Thomas Bogendoerfer,
	Mauro Carvalho Chehab
In-Reply-To: <20260715185112.1323510-1-andriy.shevchenko@linux.intel.com>

ephy_reset_gpio_flags exists solely to supply polarity to the reset GPIO.
But in practice it's kept all the same and currently only a single user
present. Drop the member and use hard coded GPIO flags instead.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 arch/mips/bcm63xx/boards/board_bcm963xx.c           | 7 +++----
 arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 3 ---
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c
index c5617b889b1c..57e916c06792 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -42,7 +42,7 @@ static struct board_info __initdata board_cvg834g = {
 	.expected_cpu_id = 0x3368,
 
 	.ephy_reset_gpio = 36,
-	.ephy_reset_gpio_flags = GPIOF_OUT_INIT_HIGH,
+
 	.has_pci = 1,
 	.has_uart0 = 1,
 	.has_uart1 = 1,
@@ -903,9 +903,8 @@ int __init board_register_devices(void)
 
 	platform_device_register(&bcm63xx_gpio_leds);
 
-	if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
-		gpio_request_one(board.ephy_reset_gpio,
-				board.ephy_reset_gpio_flags, "ephy-reset");
+	if (board.ephy_reset_gpio)
+		gpio_request_one(board.ephy_reset_gpio, GPIOF_OUT_INIT_HIGH, "ephy-reset");
 
 	return 0;
 }
diff --git a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
index 830f53f28e3f..018a56cbc328 100644
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -46,9 +46,6 @@ struct board_info {
 
 	/* External PHY reset GPIO */
 	unsigned int ephy_reset_gpio;
-
-	/* External PHY reset GPIO flags from gpio.h */
-	unsigned long ephy_reset_gpio_flags;
 };
 
 #endif /* ! BOARD_BCM963XX_H_ */
-- 
2.50.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox