* Re: [PATCH 2/2] nvme-apple: Prevent tag collision across queues even if tag space is shared
From: Nick Chan @ 2026-06-06 15:08 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Neal Gompa, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg
Cc: asahi, linux-arm-kernel, linux-nvme, linux-kernel, stable,
Yuriy Havrylyuk
In-Reply-To: <20260606-prevent-tag-collision-t8015-v1-2-93ccf4eca550@gmail.com>
Nick Chan 於 2026/6/6 晚上9:25 寫道:
> From: Yuriy Havrylyuk <yhavry@gmail.com>
>
> Apple NVMe controllers require tags of pending commands to not be shared
> across admin and IO queues. However, on Apple A11 without linear SQ, it is
> not possible for either queue to skip over some tags and must go from 0 to
> the configured maximum before wrapping around.
>
> If a pending command tag is duplicated across queues, the firmware
> crashes with: "duplicate tag error for tag N", with N being the tag.
>
> Instead of partitioning the tag space, which is not possible without
> linear SQ, prevent tag collisions by keeping track of which tags are
> currently in-flight across either queues, and return BLK_STS_RESOURCE to
> temporaily block command submission when a collision would have occurred.
>
> Cc: stable@vger.kernel.org
> Fixes: 04d8ecf37b5e ("nvme: apple: Add Apple A11 support")
> Signed-off-by: Yuriy Havrylyuk <yhavry@gmail.com>
> Co-developed-by: Nick Chan <towinchenmi@gmail.com>
> Signed-off-by: Nick Chan <towinchenmi@gmail.com>
> ---
> drivers/nvme/host/apple.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 65 insertions(+)
There are some issues with this version that make it not actually work, so a v2
will sent.
>
> diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
> index c1115e27a0d6..6354edf27225 100644
> --- a/drivers/nvme/host/apple.c
> +++ b/drivers/nvme/host/apple.c
> @@ -203,6 +203,20 @@ struct apple_nvme {
>
> int irq;
> spinlock_t lock;
> +
> + /*
> + * Tags of pending commands must be unique across both Admin and IO
> + * queue. However, on T8015, unlike T8103, without linear submission
> + * queues, it is not possible for the either queue to skip some tags,
> + * and both queues must go from 0 to their respective configured
> + * maximum.
> + *
> + * Instead of reserving some tags for the admin queue, use a bitfield
> + * to keep track of pending commands on either queue, and temporaily
> + * block command submission by returning BLK_STS_RESOURCE until the
> + * tag is freed on the other queue.
> + */
> + unsigned long t8015_active_tags;
> };
>
> static_assert(sizeof(struct nvme_command) == 64);
> @@ -290,6 +304,28 @@ static void apple_nvmmu_inval(struct apple_nvme_queue *q, unsigned int tag)
> "NVMMU TCB invalidation failed\n");
> }
>
> +static bool apple_nvme_reserve_tag_t8015(struct apple_nvme *anv,
> + struct nvme_command *cmd)
> +{
> + u16 tag = nvme_tag_from_cid(cmd->common.command_id);
> +
> + if (WARN_ON_ONCE(tag >= BITS_PER_LONG))
> + return false;
> +
> + return !test_and_set_bit(tag, &anv->t8015_active_tags);
> +}
> +
> +static void apple_nvme_release_tag_t8015(struct apple_nvme *anv,
> + __u16 command_id)
> +{
> + u16 tag = nvme_tag_from_cid(command_id);
> +
> + if (WARN_ON_ONCE(tag >= BITS_PER_LONG))
> + return;
> +
> + clear_bit(tag, &anv->t8015_active_tags);
> +}
> +
> static void apple_nvme_submit_cmd_t8015(struct apple_nvme_queue *q,
> struct nvme_command *cmd)
> {
> @@ -652,6 +688,8 @@ static inline void apple_nvme_update_cq_head(struct apple_nvme_queue *q)
> static bool apple_nvme_poll_cq(struct apple_nvme_queue *q,
> struct io_comp_batch *iob)
> {
> + struct apple_nvme *anv = queue_to_apple_nvme(q);
> + unsigned long completed_tags = 0;
> bool found = false;
>
> while (apple_nvme_cqe_pending(q)) {
> @@ -664,11 +702,26 @@ static bool apple_nvme_poll_cq(struct apple_nvme_queue *q,
> dma_rmb();
> apple_nvme_handle_cqe(q, iob, q->cq_head);
> apple_nvme_update_cq_head(q);
> +
> + if (!anv->hw->has_lsq_nvmmu) {
> + struct nvme_completion *cqe = &q->cqes[q->cq_head];
> + u16 tag = nvme_tag_from_cid(READ_ONCE(cqe->command_id));
Reading command ID here is too late since cq head has already been updated.
> +
> + if (!WARN_ON_ONCE(tag >= BITS_PER_LONG))
> + __set_bit(tag, &completed_tags);
> + }
> }
>
> if (found)
> writel(q->cq_head, q->cq_db);
>
> + if (!anv->hw->has_lsq_nvmmu && completed_tags) {
> + unsigned long tag_bit;
> +
> + for_each_set_bit(tag_bit, &completed_tags, BITS_PER_LONG)
> + clear_bit(tag_bit, &anv->t8015_active_tags);
> + }
> +
> return found;
> }
>
> @@ -790,6 +843,12 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
> if (ret)
> return ret;
>
> + if (!anv->hw->has_lsq_nvmmu &&
> + !apple_nvme_reserve_tag_t8015(anv, cmnd)) {
> + ret = BLK_STS_RESOURCE;
> + goto out_free_cmd;
Note goto out_free_cmd here.
> + }
> +
> if (blk_rq_nr_phys_segments(req)) {
> ret = apple_nvme_map_data(anv, req, cmnd);
> if (ret)
> @@ -806,6 +865,9 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
> return BLK_STS_OK;
>
> out_free_cmd:
> + if (!anv->hw->has_lsq_nvmmu)
> + apple_nvme_release_tag_t8015(anv, cmnd->common.command_id);
Combined with above this makes any attempted use of a in-use tag release that
tag, making the workaround ineffective. (and allows nvme to still "work" if
the tester is (un)lucky).
> +
> nvme_cleanup_cmd(req);
> return ret;
> }
> @@ -1165,6 +1227,9 @@ static void apple_nvme_reset_work(struct work_struct *work)
> if (ret)
> goto out;
>
> + if (!anv->hw->has_lsq_nvmmu)
> + WRITE_ONCE(anv->t8015_active_tags, 0);
> +
> dev_dbg(anv->dev, "Starting admin queue");
> apple_nvme_init_queue(&anv->adminq);
> nvme_unquiesce_admin_queue(&anv->ctrl);
>
Best regards,
Nick Chan
^ permalink raw reply
* [PATCH net-next] net: airoha: Add TCP LRO support
From: Lorenzo Bianconi @ 2026-06-06 14:45 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Lorenzo Bianconi
Cc: Alexander Lobakin, linux-arm-kernel, linux-mediatek, netdev,
Madhur Agrawal
Add hardware TCP Large Receive Offload (LRO) support to the airoha_eth
driver, leveraging the EN7581/AN7583 SoC's 8 dedicated LRO hardware queues
mapped to RX queues 24–31. LRO hw offloading does not support
Scatter-Gather (SG) so it is required to increase the page_pool allocation
order to 2 for RX queues 24–31 (LRO queues).
Performance comparison between GRO and hw LRO has been carried out using
a 10Gbps NIC:
GRO: ~2.7 Gbps
LRO: ~8.1 Gbps
Please note with respect to the previous implementation, page_pool
allocation order has been reduced from 5 to 2.
Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes in v1:
- Please note this patch depends on the following patch not applied yet
to net-next
https://lore.kernel.org/netdev/20260606-airoha_qdma_users-no-atomic-v1-1-86e2d6a1bfaf@kernel.org/T/#u
- Restrict LRO to single user QDMA.
- Introduce some more sanity checks.
- Disable scatter-gather for LRO queues.
- Run netif_receive_skb() for LRO packets.
- Link to v3: https://lore.kernel.org/r/20260528-airoha-eth-lro-v3-1-dd09c1fb000e@kernel.org
Changes in RFC v3:
- Fix double-free of the page_pool of airoha_qdma_lro_rx_process()
fails.
- Set AIROHA_LRO_PAGE_ORDER according to PAGE_SIZE.
- Add missig gso metadata for the LRO packet.
- Link to v2: https://lore.kernel.org/r/20260526-airoha-eth-lro-v2-1-24e2a9e7a397@kernel.org
Changes in RFC v2:
- Improve performances fixing buf_size computation.
- Fix possible overflow in REG_CDM_LRO_LIMIT() register configuration.
- Require the device to be not running before configuring LRO.
- Fix configuration order in airoha_fe_lro_is_enabled().
- Check skb header length in airoha_qdma_lro_rx_process().
- Do not check net_device feature in airoha_qdma_rx_process() before
executing airoha_qdma_lro_rx_process() but rely on
airoha_qdma_lro_rx_process() logic.
- Fix possible double recycle in airoha_qdma_rx_process() for LRO
packets.
- Always use AIROHA_RXQ_LRO_MAX_AGG_COUNT macro for max LRO aggregated
fragments in airoha_fe_lro_init_rx_queue().
- Link to v1: https://lore.kernel.org/r/20260520-airoha-eth-lro-v1-1-129cc33766e9@kernel.org
---
drivers/net/ethernet/airoha/airoha_eth.c | 267 +++++++++++++++++++++++++++---
drivers/net/ethernet/airoha/airoha_eth.h | 24 +++
drivers/net/ethernet/airoha/airoha_regs.h | 22 ++-
3 files changed, 290 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index a5fe08864fa3..7431b901b7fd 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -12,6 +12,7 @@
#include <net/dst_metadata.h>
#include <net/page_pool/helpers.h>
#include <net/pkt_cls.h>
+#include <net/tcp.h>
#include <uapi/linux/ppp_defs.h>
#include "airoha_regs.h"
@@ -486,6 +487,48 @@ static void airoha_fe_crsn_qsel_init(struct airoha_eth *eth)
CDM_CRSN_QSEL_Q1));
}
+static void airoha_fe_lro_init_rx_queue(struct airoha_eth *eth, int qdma_id,
+ int lro_queue_index, int qid,
+ int buf_size)
+{
+ int id = qdma_id + 1;
+
+ airoha_fe_rmw(eth, REG_CDM_LRO_LIMIT(id),
+ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK,
+ FIELD_PREP(CDM_LRO_AGG_SIZE_MASK, buf_size) |
+ FIELD_PREP(CDM_LRO_AGG_NUM_MASK,
+ AIROHA_RXQ_LRO_MAX_AGG_COUNT));
+ airoha_fe_rmw(eth, REG_CDM_LRO_AGE_TIME(id),
+ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK,
+ FIELD_PREP(CDM_LRO_AGE_TIME_MASK,
+ AIROHA_RXQ_LRO_MAX_AGE_TIME) |
+ FIELD_PREP(CDM_LRO_AGG_TIME_MASK,
+ AIROHA_RXQ_LRO_MAX_AGG_TIME));
+ airoha_fe_rmw(eth, REG_CDM_LRO_RXQ(id, lro_queue_index),
+ LRO_RXQ_MASK(lro_queue_index),
+ __field_prep(LRO_RXQ_MASK(lro_queue_index), qid));
+ airoha_fe_set(eth, REG_CDM_LRO_EN(id), BIT(lro_queue_index));
+}
+
+static void airoha_fe_lro_disable(struct airoha_eth *eth, int qdma_id)
+{
+ int i, id = qdma_id + 1;
+
+ airoha_fe_clear(eth, REG_CDM_LRO_EN(id), LRO_RXQ_EN_MASK);
+ airoha_fe_clear(eth, REG_CDM_LRO_LIMIT(id),
+ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK);
+ airoha_fe_clear(eth, REG_CDM_LRO_AGE_TIME(id),
+ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK);
+ for (i = 0; i < AIROHA_MAX_NUM_LRO_QUEUES; i++)
+ airoha_fe_clear(eth, REG_CDM_LRO_RXQ(id, i), LRO_RXQ_MASK(i));
+}
+
+static bool airoha_fe_lro_is_enabled(struct airoha_eth *eth, int qdma_id)
+{
+ return airoha_fe_get(eth, REG_CDM_LRO_EN(qdma_id + 1),
+ LRO_RXQ_EN_MASK);
+}
+
static int airoha_fe_init(struct airoha_eth *eth)
{
airoha_fe_maccr_init(eth);
@@ -603,6 +646,7 @@ static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
e->dma_addr = page_pool_get_dma_addr(page) + offset;
e->dma_len = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size));
+ WRITE_ONCE(desc->tcp_ts_reply, 0);
val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len);
WRITE_ONCE(desc->ctrl, cpu_to_le32(val));
WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr));
@@ -644,6 +688,104 @@ airoha_qdma_get_gdm_dev(struct airoha_eth *eth, struct airoha_qdma_desc *desc)
return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV);
}
+static int airoha_qdma_lro_rx_process(struct sk_buff *skb,
+ struct airoha_qdma_desc *desc)
+{
+ u32 desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+ u32 len, th_off, tcp_ack_seq, agg_count, data_off;
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
+ u32 msg1 = le32_to_cpu(READ_ONCE(desc->msg1));
+ u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2));
+ u32 msg3 = le32_to_cpu(READ_ONCE(desc->msg3));
+ struct tcphdr *th, _th;
+ u16 tcp_win, l2_len;
+ bool ipv4, ipv6;
+
+ agg_count = FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2);
+ if (agg_count <= 1)
+ return 0;
+
+ ipv4 = FIELD_GET(QDMA_ETH_RXMSG_IP4_MASK, msg1);
+ ipv6 = FIELD_GET(QDMA_ETH_RXMSG_IP6_MASK, msg1);
+ if (!ipv4 && !ipv6)
+ return -EOPNOTSUPP;
+
+ l2_len = FIELD_GET(QDMA_ETH_RXMSG_L2_LEN_MASK, msg2);
+ len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
+ if (ipv4) {
+ struct iphdr *iph, _iph;
+
+ iph = skb_header_pointer(skb, l2_len, sizeof(*iph), &_iph);
+ if (!iph)
+ return -EINVAL;
+
+ if (iph->protocol != IPPROTO_TCP)
+ return -EOPNOTSUPP;
+
+ if (iph->ihl < 5)
+ return -EINVAL;
+
+ iph = skb_header_pointer(skb, l2_len, iph->ihl << 2, &_iph);
+ if (!iph)
+ return -EINVAL;
+
+ iph->tot_len = cpu_to_be16(len - l2_len);
+ iph->check = 0;
+ iph->check = ip_fast_csum((void *)iph, iph->ihl);
+ th_off = l2_len + (iph->ihl << 2);
+ } else {
+ struct ipv6hdr *ip6h, _ip6h;
+
+ ip6h = skb_header_pointer(skb, l2_len, sizeof(*ip6h), &_ip6h);
+ if (!ip6h)
+ return -EINVAL;
+
+ if (ip6h->nexthdr != NEXTHDR_TCP)
+ return -EOPNOTSUPP;
+
+ th_off = l2_len + sizeof(*ip6h);
+ ip6h->payload_len = cpu_to_be16(len - th_off);
+ }
+
+ tcp_win = FIELD_GET(QDMA_ETH_RXMSG_TCP_WIN_MASK, msg3);
+ tcp_ack_seq = le32_to_cpu(READ_ONCE(desc->data));
+
+ th = skb_header_pointer(skb, th_off, sizeof(*th), &_th);
+ if (!th)
+ return -EINVAL;
+
+ th->ack_seq = cpu_to_be32(tcp_ack_seq);
+ th->window = cpu_to_be16(tcp_win);
+
+ /* Check tcp timestamp option */
+ if (th->doff == (sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4) {
+ u32 topt;
+
+ th = skb_header_pointer(skb, th_off, th->doff << 2, &_th);
+ if (!th)
+ return -EINVAL;
+
+ topt = get_unaligned_be32(th + 1);
+ if (topt == ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
+ u8 *ptr = (u8 *)th + sizeof(*th) + 2 * sizeof(__be32);
+ __le32 tcp_ts_reply = READ_ONCE(desc->tcp_ts_reply);
+
+ put_unaligned_be32(le32_to_cpu(tcp_ts_reply), ptr);
+ }
+ }
+
+ data_off = th_off + (th->doff << 2);
+ if (len <= data_off)
+ return -EINVAL;
+
+ shinfo->gso_type = ipv4 ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6;
+ shinfo->gso_size = (len - data_off) / agg_count;
+ shinfo->gso_segs = agg_count;
+
+ return 0;
+}
+
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
{
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
@@ -694,9 +836,17 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
__skb_put(q->skb, len);
skb_mark_for_recycle(q->skb);
q->skb->dev = netdev;
- q->skb->protocol = eth_type_trans(q->skb, netdev);
q->skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(q->skb, qid);
+
+ if (airoha_qdma_lro_rx_process(q->skb, desc) < 0) {
+ netdev->stats.rx_dropped++;
+ dev_kfree_skb(q->skb);
+ q->skb = NULL;
+ continue;
+ }
+
+ q->skb->protocol = eth_type_trans(q->skb, netdev);
} else { /* scattered frame */
struct skb_shared_info *shinfo = skb_shinfo(q->skb);
int nr_frags = shinfo->nr_frags;
@@ -741,7 +891,10 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
false);
done++;
- napi_gro_receive(&q->napi, q->skb);
+ if (skb_is_gso(q->skb))
+ netif_receive_skb(q->skb);
+ else
+ napi_gro_receive(&q->napi, q->skb);
q->skb = NULL;
continue;
free_frag:
@@ -787,12 +940,10 @@ static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
struct airoha_qdma *qdma, int ndesc)
{
- const struct page_pool_params pp_params = {
- .order = 0,
+ struct page_pool_params pp_params = {
.pool_size = 256,
.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
.dma_dir = DMA_FROM_DEVICE,
- .max_len = PAGE_SIZE,
.nid = NUMA_NO_NODE,
.dev = qdma->eth->dev,
.napi = &q->napi,
@@ -800,9 +951,10 @@ static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
struct airoha_eth *eth = qdma->eth;
int qid = q - &qdma->q_rx[0], thr;
dma_addr_t dma_addr;
+ bool lro_q;
- q->buf_size = PAGE_SIZE / 2;
q->qdma = qdma;
+ lro_q = airoha_qdma_is_lro_queue(q);
q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry),
GFP_KERNEL);
@@ -814,6 +966,9 @@ static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
if (!q->desc)
return -ENOMEM;
+ pp_params.order = lro_q ? AIROHA_LRO_PAGE_ORDER : 0;
+ pp_params.max_len = PAGE_SIZE << pp_params.order;
+
q->page_pool = page_pool_create(&pp_params);
if (IS_ERR(q->page_pool)) {
int err = PTR_ERR(q->page_pool);
@@ -822,6 +977,7 @@ static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
return err;
}
+ q->buf_size = lro_q ? pp_params.max_len : pp_params.max_len / 2;
q->ndesc = ndesc;
netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll);
@@ -835,7 +991,12 @@ static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
FIELD_PREP(RX_RING_THR_MASK, thr));
airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head));
- airoha_qdma_set(qdma, REG_RX_SCATTER_CFG(qid), RX_RING_SG_EN_MASK);
+ if (lro_q)
+ airoha_qdma_clear(qdma, REG_RX_SCATTER_CFG(qid),
+ RX_RING_SG_EN_MASK);
+ else
+ airoha_qdma_set(qdma, REG_RX_SCATTER_CFG(qid),
+ RX_RING_SG_EN_MASK);
airoha_qdma_fill_rx_queue(q);
@@ -857,6 +1018,7 @@ static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
page_pool_get_dma_dir(q->page_pool));
page_pool_put_full_page(q->page_pool, page, false);
/* Reset DMA descriptor */
+ WRITE_ONCE(desc->tcp_ts_reply, 0);
WRITE_ONCE(desc->ctrl, 0);
WRITE_ONCE(desc->addr, 0);
WRITE_ONCE(desc->data, 0);
@@ -1778,6 +1940,18 @@ static int airoha_dev_open(struct net_device *netdev)
struct airoha_gdm_port *port = dev->port;
u32 cur_len, pse_port = FE_PSE_PORT_PPE1;
struct airoha_qdma *qdma = dev->qdma;
+ struct airoha_eth *eth = qdma->eth;
+ int qdma_id = qdma - ð->qdma[0];
+
+ /* HW LRO is configured on the QDMA and it is shared between
+ * all the devices using it. Refuse to open a second device on
+ * the same QDMA if LRO is enabled on any device sharing it.
+ */
+ if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) {
+ netdev_warn(netdev, "required to disable LRO on QDMA%d\n",
+ qdma_id);
+ return -EBUSY;
+ }
netif_tx_start_all_queues(netdev);
err = airoha_set_vip_for_gdm_port(dev, true);
@@ -1785,13 +1959,13 @@ static int airoha_dev_open(struct net_device *netdev)
return err;
if (netdev_uses_dsa(netdev))
- airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
+ airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id),
GDM_STAG_EN_MASK);
else
- airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
+ airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id),
GDM_STAG_EN_MASK);
- cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id),
+ cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id),
GDM_LONG_LEN_MASK);
if (!port->users || len > cur_len) {
/* Opening a sibling net_device with a larger MTU updates the
@@ -1799,7 +1973,7 @@ static int airoha_dev_open(struct net_device *netdev)
* multiple net_devices with different MTUs to share the same
* GDM port.
*/
- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id),
+ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id),
GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK,
FIELD_PREP(GDM_SHORT_LEN_MASK, 60) |
FIELD_PREP(GDM_LONG_LEN_MASK, len));
@@ -1811,10 +1985,9 @@ static int airoha_dev_open(struct net_device *netdev)
GLOBAL_CFG_RX_DMA_EN_MASK);
qdma->users++;
- if (!airoha_is_lan_gdm_dev(dev) &&
- airoha_ppe_is_enabled(qdma->eth, 1))
+ if (!airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1))
pse_port = FE_PSE_PORT_PPE2;
- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id),
pse_port);
return 0;
@@ -1849,6 +2022,7 @@ static int airoha_dev_stop(struct net_device *netdev)
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
struct airoha_qdma *qdma = dev->qdma;
+ struct airoha_eth *eth = qdma->eth;
int i;
netif_tx_disable(netdev);
@@ -1857,10 +2031,9 @@ static int airoha_dev_stop(struct net_device *netdev)
netdev_tx_reset_subqueue(netdev, i);
if (--port->users)
- airoha_set_port_mtu(dev->eth, port);
+ airoha_set_port_mtu(eth, port);
else
- airoha_set_gdm_port_fwd_cfg(qdma->eth,
- REG_GDM_FWD_CFG(port->id),
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id),
FE_PSE_PORT_DROP);
if (!--qdma->users) {
@@ -2154,6 +2327,56 @@ int airoha_get_fe_port(struct airoha_gdm_dev *dev)
}
}
+static netdev_features_t airoha_dev_fix_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_qdma *qdma = dev->qdma;
+
+ if (qdma->users > 1)
+ features &= ~NETIF_F_LRO;
+
+ return features;
+}
+
+static int airoha_dev_set_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ netdev_features_t diff = netdev->features ^ features;
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_qdma *qdma = dev->qdma;
+ struct airoha_eth *eth = qdma->eth;
+ int qdma_id = qdma - ð->qdma[0];
+
+ if (!(diff & NETIF_F_LRO))
+ return 0;
+
+ if (features & NETIF_F_LRO) {
+ int i, lro_queue_index = 0;
+
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
+ struct airoha_queue *q = &qdma->q_rx[i];
+ u32 size;
+
+ if (!q->ndesc)
+ continue;
+
+ if (!airoha_qdma_is_lro_queue(q))
+ continue;
+
+ size = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size));
+ size = min_t(u32, size, CDM_LRO_AGG_SIZE_MASK);
+ airoha_fe_lro_init_rx_queue(eth, qdma_id,
+ lro_queue_index, i, size);
+ lro_queue_index++;
+ }
+ } else {
+ airoha_fe_lro_disable(eth, qdma_id);
+ }
+
+ return 0;
+}
+
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
@@ -3082,6 +3305,8 @@ static const struct net_device_ops airoha_netdev_ops = {
.ndo_stop = airoha_dev_stop,
.ndo_change_mtu = airoha_dev_change_mtu,
.ndo_select_queue = airoha_dev_select_queue,
+ .ndo_fix_features = airoha_dev_fix_features,
+ .ndo_set_features = airoha_dev_set_features,
.ndo_start_xmit = airoha_dev_xmit,
.ndo_get_stats64 = airoha_dev_get_stats64,
.ndo_set_mac_address = airoha_dev_set_macaddr,
@@ -3169,11 +3394,9 @@ static int airoha_alloc_gdm_device(struct airoha_eth *eth,
netdev->ethtool_ops = &airoha_ethtool_ops;
netdev->max_mtu = AIROHA_MAX_MTU;
netdev->watchdog_timeo = 5 * HZ;
- netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 |
- NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO |
- NETIF_F_HW_TC;
- netdev->features |= netdev->hw_features;
- netdev->vlan_features = netdev->hw_features;
+ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO;
+ netdev->features |= AIROHA_HW_FEATURES;
+ netdev->vlan_features = AIROHA_HW_FEATURES;
SET_NETDEV_DEV(netdev, eth->dev);
/* reserve hw queues for HTB offloading */
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index e89c2dff411f..71d439f89f02 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -44,6 +44,18 @@
(_n) == 15 ? 128 : \
(_n) == 0 ? 1024 : 16)
+#define AIROHA_LRO_PAGE_ORDER order_base_2(SZ_16K / PAGE_SIZE)
+#define AIROHA_MAX_NUM_LRO_QUEUES 8
+#define AIROHA_RXQ_LRO_EN_MASK 0xff000000
+#define AIROHA_RXQ_LRO_MAX_AGG_COUNT 64
+#define AIROHA_RXQ_LRO_MAX_AGG_TIME 100
+#define AIROHA_RXQ_LRO_MAX_AGE_TIME 2000
+
+#define AIROHA_HW_FEATURES \
+ (NETIF_F_IP_CSUM | NETIF_F_RXCSUM | \
+ NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | \
+ NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_TC)
+
#define PSE_RSV_PAGES 128
#define PSE_QUEUE_RSV_PAGES 64
@@ -671,6 +683,18 @@ static inline bool airoha_is_7583(struct airoha_eth *eth)
return eth->soc->version == 0x7583;
}
+static inline bool airoha_qdma_is_lro_queue(struct airoha_queue *q)
+{
+ struct airoha_qdma *qdma = q->qdma;
+ int qid = q - &qdma->q_rx[0];
+
+ /* EN7581 SoC supports at most 8 LRO rx queues */
+ BUILD_BUG_ON(hweight32(AIROHA_RXQ_LRO_EN_MASK) >
+ AIROHA_MAX_NUM_LRO_QUEUES);
+
+ return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid));
+}
+
int airoha_get_fe_port(struct airoha_gdm_dev *dev);
bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
struct airoha_gdm_dev *dev);
diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
index 436f3c8779c1..dfc786583774 100644
--- a/drivers/net/ethernet/airoha/airoha_regs.h
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
@@ -122,6 +122,20 @@
#define CDM_CRSN_QSEL_REASON_MASK(_n) \
GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3))
+#define REG_CDM_LRO_RXQ(_n, _m) (CDM_BASE(_n) + 0x78 + ((_m) & 0x4))
+#define LRO_RXQ_MASK(_n) GENMASK(4 + (((_n) & 0x3) << 3), ((_n) & 0x3) << 3)
+
+#define REG_CDM_LRO_EN(_n) (CDM_BASE(_n) + 0x80)
+#define LRO_RXQ_EN_MASK GENMASK(7, 0)
+
+#define REG_CDM_LRO_LIMIT(_n) (CDM_BASE(_n) + 0x84)
+#define CDM_LRO_AGG_NUM_MASK GENMASK(23, 16)
+#define CDM_LRO_AGG_SIZE_MASK GENMASK(15, 0)
+
+#define REG_CDM_LRO_AGE_TIME(_n) (CDM_BASE(_n) + 0x88)
+#define CDM_LRO_AGE_TIME_MASK GENMASK(31, 16)
+#define CDM_LRO_AGG_TIME_MASK GENMASK(15, 0)
+
#define REG_GDM_FWD_CFG(_n) GDM_BASE(_n)
#define GDM_PAD_EN_MASK BIT(28)
#define GDM_DROP_CRC_ERR_MASK BIT(23)
@@ -883,9 +897,15 @@
#define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21)
#define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16)
#define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0)
+/* RX MSG2 */
+#define QDMA_ETH_RXMSG_AGG_COUNT_MASK GENMASK(31, 24)
+#define QDMA_ETH_RXMSG_L2_LEN_MASK GENMASK(6, 0)
+/* RX MSG3 */
+#define QDMA_ETH_RXMSG_AGG_LEN_MASK GENMASK(31, 16)
+#define QDMA_ETH_RXMSG_TCP_WIN_MASK GENMASK(15, 0)
struct airoha_qdma_desc {
- __le32 rsv;
+ __le32 tcp_ts_reply;
__le32 ctrl;
__le32 addr;
__le32 data;
---
base-commit: 1fc7e55677b09ff8a38f90fb5563f80b067d5475
change-id: 20260520-airoha-eth-lro-a5d1c3631811
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: [PATCH 2/2] nvme-apple: Prevent tag collision across queues even if tag space is shared
From: David Laight @ 2026-06-06 14:29 UTC (permalink / raw)
To: Nick Chan
Cc: Sven Peter, Janne Grunau, Neal Gompa, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg, asahi, linux-arm-kernel,
linux-nvme, linux-kernel, stable, Yuriy Havrylyuk
In-Reply-To: <20260606-prevent-tag-collision-t8015-v1-2-93ccf4eca550@gmail.com>
On Sat, 06 Jun 2026 21:25:26 +0800
Nick Chan <towinchenmi@gmail.com> wrote:
> From: Yuriy Havrylyuk <yhavry@gmail.com>
>
> Apple NVMe controllers require tags of pending commands to not be shared
> across admin and IO queues. However, on Apple A11 without linear SQ, it is
> not possible for either queue to skip over some tags and must go from 0 to
> the configured maximum before wrapping around.
>
> If a pending command tag is duplicated across queues, the firmware
> crashes with: "duplicate tag error for tag N", with N being the tag.
>
> Instead of partitioning the tag space, which is not possible without
> linear SQ, prevent tag collisions by keeping track of which tags are
> currently in-flight across either queues, and return BLK_STS_RESOURCE to
> temporaily block command submission when a collision would have occurred.
I look at using the atomic64_xxx() functions rather than the bitmask ones.
The for_each_bit_set() loop is then an atmomic64_andnot() call.
-- David
>
> Cc: stable@vger.kernel.org
> Fixes: 04d8ecf37b5e ("nvme: apple: Add Apple A11 support")
> Signed-off-by: Yuriy Havrylyuk <yhavry@gmail.com>
> Co-developed-by: Nick Chan <towinchenmi@gmail.com>
> Signed-off-by: Nick Chan <towinchenmi@gmail.com>
> ---
> drivers/nvme/host/apple.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 65 insertions(+)
>
> diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
> index c1115e27a0d6..6354edf27225 100644
> --- a/drivers/nvme/host/apple.c
> +++ b/drivers/nvme/host/apple.c
> @@ -203,6 +203,20 @@ struct apple_nvme {
>
> int irq;
> spinlock_t lock;
> +
> + /*
> + * Tags of pending commands must be unique across both Admin and IO
> + * queue. However, on T8015, unlike T8103, without linear submission
> + * queues, it is not possible for the either queue to skip some tags,
> + * and both queues must go from 0 to their respective configured
> + * maximum.
> + *
> + * Instead of reserving some tags for the admin queue, use a bitfield
> + * to keep track of pending commands on either queue, and temporaily
> + * block command submission by returning BLK_STS_RESOURCE until the
> + * tag is freed on the other queue.
> + */
> + unsigned long t8015_active_tags;
> };
>
> static_assert(sizeof(struct nvme_command) == 64);
> @@ -290,6 +304,28 @@ static void apple_nvmmu_inval(struct apple_nvme_queue *q, unsigned int tag)
> "NVMMU TCB invalidation failed\n");
> }
>
> +static bool apple_nvme_reserve_tag_t8015(struct apple_nvme *anv,
> + struct nvme_command *cmd)
> +{
> + u16 tag = nvme_tag_from_cid(cmd->common.command_id);
> +
> + if (WARN_ON_ONCE(tag >= BITS_PER_LONG))
> + return false;
> +
> + return !test_and_set_bit(tag, &anv->t8015_active_tags);
> +}
> +
> +static void apple_nvme_release_tag_t8015(struct apple_nvme *anv,
> + __u16 command_id)
> +{
> + u16 tag = nvme_tag_from_cid(command_id);
> +
> + if (WARN_ON_ONCE(tag >= BITS_PER_LONG))
> + return;
> +
> + clear_bit(tag, &anv->t8015_active_tags);
> +}
> +
> static void apple_nvme_submit_cmd_t8015(struct apple_nvme_queue *q,
> struct nvme_command *cmd)
> {
> @@ -652,6 +688,8 @@ static inline void apple_nvme_update_cq_head(struct apple_nvme_queue *q)
> static bool apple_nvme_poll_cq(struct apple_nvme_queue *q,
> struct io_comp_batch *iob)
> {
> + struct apple_nvme *anv = queue_to_apple_nvme(q);
> + unsigned long completed_tags = 0;
> bool found = false;
>
> while (apple_nvme_cqe_pending(q)) {
> @@ -664,11 +702,26 @@ static bool apple_nvme_poll_cq(struct apple_nvme_queue *q,
> dma_rmb();
> apple_nvme_handle_cqe(q, iob, q->cq_head);
> apple_nvme_update_cq_head(q);
> +
> + if (!anv->hw->has_lsq_nvmmu) {
> + struct nvme_completion *cqe = &q->cqes[q->cq_head];
> + u16 tag = nvme_tag_from_cid(READ_ONCE(cqe->command_id));
> +
> + if (!WARN_ON_ONCE(tag >= BITS_PER_LONG))
> + __set_bit(tag, &completed_tags);
> + }
> }
>
> if (found)
> writel(q->cq_head, q->cq_db);
>
> + if (!anv->hw->has_lsq_nvmmu && completed_tags) {
> + unsigned long tag_bit;
> +
> + for_each_set_bit(tag_bit, &completed_tags, BITS_PER_LONG)
> + clear_bit(tag_bit, &anv->t8015_active_tags);
> + }
> +
> return found;
> }
>
> @@ -790,6 +843,12 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
> if (ret)
> return ret;
>
> + if (!anv->hw->has_lsq_nvmmu &&
> + !apple_nvme_reserve_tag_t8015(anv, cmnd)) {
> + ret = BLK_STS_RESOURCE;
> + goto out_free_cmd;
> + }
> +
> if (blk_rq_nr_phys_segments(req)) {
> ret = apple_nvme_map_data(anv, req, cmnd);
> if (ret)
> @@ -806,6 +865,9 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
> return BLK_STS_OK;
>
> out_free_cmd:
> + if (!anv->hw->has_lsq_nvmmu)
> + apple_nvme_release_tag_t8015(anv, cmnd->common.command_id);
> +
> nvme_cleanup_cmd(req);
> return ret;
> }
> @@ -1165,6 +1227,9 @@ static void apple_nvme_reset_work(struct work_struct *work)
> if (ret)
> goto out;
>
> + if (!anv->hw->has_lsq_nvmmu)
> + WRITE_ONCE(anv->t8015_active_tags, 0);
> +
> dev_dbg(anv->dev, "Starting admin queue");
> apple_nvme_init_queue(&anv->adminq);
> nvme_unquiesce_admin_queue(&anv->ctrl);
>
^ permalink raw reply
* [PATCH 2/2] nvme-apple: Prevent tag collision across queues even if tag space is shared
From: Nick Chan @ 2026-06-06 13:25 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Neal Gompa, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg
Cc: asahi, linux-arm-kernel, linux-nvme, linux-kernel, stable,
Nick Chan, Yuriy Havrylyuk
In-Reply-To: <20260606-prevent-tag-collision-t8015-v1-0-93ccf4eca550@gmail.com>
From: Yuriy Havrylyuk <yhavry@gmail.com>
Apple NVMe controllers require tags of pending commands to not be shared
across admin and IO queues. However, on Apple A11 without linear SQ, it is
not possible for either queue to skip over some tags and must go from 0 to
the configured maximum before wrapping around.
If a pending command tag is duplicated across queues, the firmware
crashes with: "duplicate tag error for tag N", with N being the tag.
Instead of partitioning the tag space, which is not possible without
linear SQ, prevent tag collisions by keeping track of which tags are
currently in-flight across either queues, and return BLK_STS_RESOURCE to
temporaily block command submission when a collision would have occurred.
Cc: stable@vger.kernel.org
Fixes: 04d8ecf37b5e ("nvme: apple: Add Apple A11 support")
Signed-off-by: Yuriy Havrylyuk <yhavry@gmail.com>
Co-developed-by: Nick Chan <towinchenmi@gmail.com>
Signed-off-by: Nick Chan <towinchenmi@gmail.com>
---
drivers/nvme/host/apple.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index c1115e27a0d6..6354edf27225 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -203,6 +203,20 @@ struct apple_nvme {
int irq;
spinlock_t lock;
+
+ /*
+ * Tags of pending commands must be unique across both Admin and IO
+ * queue. However, on T8015, unlike T8103, without linear submission
+ * queues, it is not possible for the either queue to skip some tags,
+ * and both queues must go from 0 to their respective configured
+ * maximum.
+ *
+ * Instead of reserving some tags for the admin queue, use a bitfield
+ * to keep track of pending commands on either queue, and temporaily
+ * block command submission by returning BLK_STS_RESOURCE until the
+ * tag is freed on the other queue.
+ */
+ unsigned long t8015_active_tags;
};
static_assert(sizeof(struct nvme_command) == 64);
@@ -290,6 +304,28 @@ static void apple_nvmmu_inval(struct apple_nvme_queue *q, unsigned int tag)
"NVMMU TCB invalidation failed\n");
}
+static bool apple_nvme_reserve_tag_t8015(struct apple_nvme *anv,
+ struct nvme_command *cmd)
+{
+ u16 tag = nvme_tag_from_cid(cmd->common.command_id);
+
+ if (WARN_ON_ONCE(tag >= BITS_PER_LONG))
+ return false;
+
+ return !test_and_set_bit(tag, &anv->t8015_active_tags);
+}
+
+static void apple_nvme_release_tag_t8015(struct apple_nvme *anv,
+ __u16 command_id)
+{
+ u16 tag = nvme_tag_from_cid(command_id);
+
+ if (WARN_ON_ONCE(tag >= BITS_PER_LONG))
+ return;
+
+ clear_bit(tag, &anv->t8015_active_tags);
+}
+
static void apple_nvme_submit_cmd_t8015(struct apple_nvme_queue *q,
struct nvme_command *cmd)
{
@@ -652,6 +688,8 @@ static inline void apple_nvme_update_cq_head(struct apple_nvme_queue *q)
static bool apple_nvme_poll_cq(struct apple_nvme_queue *q,
struct io_comp_batch *iob)
{
+ struct apple_nvme *anv = queue_to_apple_nvme(q);
+ unsigned long completed_tags = 0;
bool found = false;
while (apple_nvme_cqe_pending(q)) {
@@ -664,11 +702,26 @@ static bool apple_nvme_poll_cq(struct apple_nvme_queue *q,
dma_rmb();
apple_nvme_handle_cqe(q, iob, q->cq_head);
apple_nvme_update_cq_head(q);
+
+ if (!anv->hw->has_lsq_nvmmu) {
+ struct nvme_completion *cqe = &q->cqes[q->cq_head];
+ u16 tag = nvme_tag_from_cid(READ_ONCE(cqe->command_id));
+
+ if (!WARN_ON_ONCE(tag >= BITS_PER_LONG))
+ __set_bit(tag, &completed_tags);
+ }
}
if (found)
writel(q->cq_head, q->cq_db);
+ if (!anv->hw->has_lsq_nvmmu && completed_tags) {
+ unsigned long tag_bit;
+
+ for_each_set_bit(tag_bit, &completed_tags, BITS_PER_LONG)
+ clear_bit(tag_bit, &anv->t8015_active_tags);
+ }
+
return found;
}
@@ -790,6 +843,12 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
if (ret)
return ret;
+ if (!anv->hw->has_lsq_nvmmu &&
+ !apple_nvme_reserve_tag_t8015(anv, cmnd)) {
+ ret = BLK_STS_RESOURCE;
+ goto out_free_cmd;
+ }
+
if (blk_rq_nr_phys_segments(req)) {
ret = apple_nvme_map_data(anv, req, cmnd);
if (ret)
@@ -806,6 +865,9 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_STS_OK;
out_free_cmd:
+ if (!anv->hw->has_lsq_nvmmu)
+ apple_nvme_release_tag_t8015(anv, cmnd->common.command_id);
+
nvme_cleanup_cmd(req);
return ret;
}
@@ -1165,6 +1227,9 @@ static void apple_nvme_reset_work(struct work_struct *work)
if (ret)
goto out;
+ if (!anv->hw->has_lsq_nvmmu)
+ WRITE_ONCE(anv->t8015_active_tags, 0);
+
dev_dbg(anv->dev, "Starting admin queue");
apple_nvme_init_queue(&anv->adminq);
nvme_unquiesce_admin_queue(&anv->ctrl);
--
2.54.0
^ permalink raw reply related
* [PATCH 1/2] nvme-apple: Only limit admin queue tag space when with Linear SQ is present
From: Nick Chan @ 2026-06-06 13:25 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Neal Gompa, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg
Cc: asahi, linux-arm-kernel, linux-nvme, linux-kernel, stable,
Nick Chan
In-Reply-To: <20260606-prevent-tag-collision-t8015-v1-0-93ccf4eca550@gmail.com>
Apple NVMe controllers require tags of pending commands to not be shared
across admin and IO queues. However, on Apple A11 without linear SQ, it is
not possible for either queue to skip over some tags and must go from 0 to
the configured maximum before wrapping around.
As a result, in order to prevent tag collision, dynamic tag reservation
while a command is in-flight becomes necessary. In this context, there is
no reason to limit the admin queue's tag space, as it is not helpful in
preventing tag collision.
Cc: stable@vger.kernel.org
Fixes: 04d8ecf37b5e ("nvme: apple: Add Apple A11 support")
Signed-off-by: Nick Chan <towinchenmi@gmail.com>
---
drivers/nvme/host/apple.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index c692fc73babf..c1115e27a0d6 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -1303,7 +1303,10 @@ static int apple_nvme_alloc_tagsets(struct apple_nvme *anv)
anv->admin_tagset.ops = &apple_nvme_mq_admin_ops;
anv->admin_tagset.nr_hw_queues = 1;
- anv->admin_tagset.queue_depth = APPLE_NVME_AQ_MQ_TAG_DEPTH;
+ if (anv->hw->has_lsq_nvmmu)
+ anv->admin_tagset.queue_depth = APPLE_NVME_AQ_MQ_TAG_DEPTH;
+ else
+ anv->admin_tagset.queue_depth = anv->hw->max_queue_depth - 1;
anv->admin_tagset.timeout = NVME_ADMIN_TIMEOUT;
anv->admin_tagset.numa_node = NUMA_NO_NODE;
anv->admin_tagset.cmd_size = sizeof(struct apple_nvme_iod);
--
2.54.0
^ permalink raw reply related
* [PATCH 0/2] nvme-apple: Prevent tag collision across queues on Apple A11
From: Nick Chan @ 2026-06-06 13:25 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Neal Gompa, Keith Busch, Jens Axboe,
Christoph Hellwig, Sagi Grimberg
Cc: asahi, linux-arm-kernel, linux-nvme, linux-kernel, stable,
Nick Chan, Yuriy Havrylyuk
Apple NVMe controllers require tags of pending commands to not be shared
across admin and IO queues.
If a pending command tag is duplicated across queues, the firmware
crashes with: "duplicate tag error for tag N", with N being the tag.
On Apple M1 or above, this is worked around by partitioning the tag
space between the admin and IO queue.
However, on Apple A11 without linear SQ, it is not possible for either
queue to skip over some tags and must go from 0 to the configured maximum
before wrapping around.
Instead of partitioning the tag space, which is not possible without
linear SQ, prevent tag collisions by keeping track of which tags are
currently in-flight across either queues, and return BLK_STS_RESOURCE to
temporaily block command submission when a collision would have occured.
While fixing the issue, it became apparent the admin queue tag space
is limited even on Apple A11. There is no reason to do this as it hampers
performance and does not help preventing tag collisions, so also allow
the admin queue to use the full tag space.
Tested on iPhone 8, iPhone X and Macbook Pro (14-inch, M1 Pro, 2021).
Signed-off-by: Nick Chan <towinchenmi@gmail.com>
---
Nick Chan (1):
nvme-apple: Only limit admin queue tag space when with Linear SQ is present
Yuriy Havrylyuk (1):
nvme-apple: Prevent tag collision across queues even if tag space is shared
drivers/nvme/host/apple.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 69 insertions(+), 1 deletion(-)
---
base-commit: e43ffb69e0438cddd72aaa30898b4dc446f664f8
change-id: 20260606-prevent-tag-collision-t8015-1c8adb3234de
Best regards,
--
Nick Chan <towinchenmi@gmail.com>
^ permalink raw reply
* [PATCH] hwrng: atmel - drop __maybe_unused from atmel_trng_pm_ops
From: Thorsten Blum @ 2026-06-06 13:17 UTC (permalink / raw)
To: Olivia Mackall, Herbert Xu, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Sakari Ailus, AngeloGioacchino Del Regno
Cc: Thorsten Blum, linux-crypto, linux-arm-kernel, linux-kernel
Since atmel_trng_driver keeps atmel_trng_pm_ops referenced and pm_ptr()
uses IS_ENABLED(), which allows the compiler to optimize away unused
variables, drop the redundant __maybe_unused annotation.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/char/hw_random/atmel-rng.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
index 6ed24be3481d..10082add0886 100644
--- a/drivers/char/hw_random/atmel-rng.c
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -186,7 +186,7 @@ static int __maybe_unused atmel_trng_runtime_resume(struct device *dev)
return atmel_trng_init(trng);
}
-static const struct dev_pm_ops __maybe_unused atmel_trng_pm_ops = {
+static const struct dev_pm_ops atmel_trng_pm_ops = {
SET_RUNTIME_PM_OPS(atmel_trng_runtime_suspend,
atmel_trng_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
base-commit: 79bbe453e5bfa6e1c6aa2e8329bfc8f152b81c9b
^ permalink raw reply related
* Re: [PATCH v3 1/3] dt-bindings: display: msm: qcm2290: Add Shikra MDSS
From: Dmitry Baryshkov @ 2026-06-06 12:23 UTC (permalink / raw)
To: Nabige Aala
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Krishna Manikandan,
Loic Poulain, Bjorn Andersson, Konrad Dybcio, Will Deacon,
Robin Murphy, Joerg Roedel (AMD), linux-arm-msm, dri-devel,
freedreno, devicetree, linux-kernel, iommu, linux-arm-kernel
In-Reply-To: <20260605-shikra-display-v3-1-9846ba5fe635@oss.qualcomm.com>
On Fri, Jun 05, 2026 at 03:48:51PM +0530, Nabige Aala wrote:
> Shikra reuses the same MDSS/DPU 6.5 hardware as QCM2290. Extend
> the existing qcm2290 bindings to cover Shikra by adding fallback
> compatible chains for MDSS, DPU and DSI controller nodes rather
> than introducing a separate binding file.
>
> Signed-off-by: Nabige Aala <nabige.aala@oss.qualcomm.com>
> ---
> .../bindings/display/msm/dsi-controller-main.yaml | 4 ++++
> .../bindings/display/msm/qcom,qcm2290-dpu.yaml | 7 +++++--
> .../bindings/display/msm/qcom,qcm2290-mdss.yaml | 22 +++++++++++++++-------
> 3 files changed, 24 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> index dbc0613e427e..ab2cfd6d6e3e 100644
> --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> @@ -57,6 +57,10 @@ properties:
> - const: qcom,eliza-dsi-ctrl
> - const: qcom,sm8750-dsi-ctrl
> - const: qcom,mdss-dsi-ctrl
> + - items:
> + - const: qcom,shikra-dsi-ctrl
> + - const: qcom,qcm2290-dsi-ctrl
> + - const: qcom,mdss-dsi-ctrl
Wrong sort order, qcm2290 < sm8750
> - enum:
> - qcom,dsi-ctrl-6g-qcm2290
> - qcom,mdss-dsi-ctrl # This should always come with an SoC-specific compatible
> diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml
> index be6cd8adb3b6..e166a73651df 100644
> --- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml
> @@ -13,8 +13,11 @@ $ref: /schemas/display/msm/dpu-common.yaml#
>
> properties:
> compatible:
> - const: qcom,qcm2290-dpu
> -
> + oneOf:
> + - const: qcom,qcm2290-dpu
> + - items:
> + - const: qcom,shikra-dpu
> + - const: qcom,qcm2290-dpu
> reg:
> items:
> - description: Address offset and size for mdp register set
> diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
> index bb09ecd1a5b4..ef21b2c263f2 100644
> --- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
> @@ -4,7 +4,7 @@
> $id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-mdss.yaml#
> $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> -title: Qualcomm QCM220 Display MDSS
> +title: Qualcomm QCM2290 and Shikra Display MDSS
>
> maintainers:
> - Loic Poulain <loic.poulain@linaro.org>
> @@ -12,13 +12,18 @@ maintainers:
> description:
> Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
> sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS
> - are mentioned for QCM2290 target.
> + are mentioned for QCM2290 and Shikra targets. Shikra uses the same MDSS/DPU/DSI
> + hardware as QCM2290 (DPU 6.5) and shares the same register layout.
>
> $ref: /schemas/display/msm/mdss-common.yaml#
>
> properties:
> compatible:
> - const: qcom,qcm2290-mdss
> + oneOf:
> + - const: qcom,qcm2290-mdss
> + - items:
> + - const: qcom,shikra-mdss
> + - const: qcom,qcm2290-mdss
>
> clocks:
> items:
> @@ -52,7 +57,11 @@ patternProperties:
>
> properties:
> compatible:
> - const: qcom,qcm2290-dpu
> + oneOf:
> + - const: qcom,qcm2290-dpu
> + - items:
> + - const: qcom,shikra-dpu
> + - const: qcom,qcm2290-dpu
Use contains:
>
> "^dsi@[0-9a-f]+$":
> type: object
> @@ -60,9 +69,8 @@ patternProperties:
>
> properties:
> compatible:
> - items:
> - - const: qcom,qcm2290-dsi-ctrl
> - - const: qcom,mdss-dsi-ctrl
> + contains:
> + const: qcom,qcm2290-dsi-ctrl
>
> "^phy@[0-9a-f]+$":
> type: object
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v3 2/3] arm64: defconfig: Enable ILI7807S DSI panel driver
From: Dmitry Baryshkov @ 2026-06-06 12:17 UTC (permalink / raw)
To: Nabige Aala
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Krishna Manikandan,
Loic Poulain, Bjorn Andersson, Konrad Dybcio, Will Deacon,
Robin Murphy, Joerg Roedel (AMD), linux-arm-msm, dri-devel,
freedreno, devicetree, linux-kernel, iommu, linux-arm-kernel
In-Reply-To: <20260605-shikra-display-v3-2-9846ba5fe635@oss.qualcomm.com>
On Fri, Jun 05, 2026 at 03:48:52PM +0530, Nabige Aala wrote:
> Enable the ILI7807S 1080x1920 video-mode DSI panel driver as a module,
> used on the Shikra CQM EVK board.
>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Signed-off-by: Nabige Aala <nabige.aala@oss.qualcomm.com>
> ---
> arch/arm64/configs/defconfig | 1 +
> 1 file changed, 1 insertion(+)
Okay, you are really not reading any feedback. This patch doesn't belong
here. Move it to the series adding the actual DT with the panel.
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v2 2/2] KVM: arm64: Bound used_lrs when flushing the pKVM hyp vCPU
From: Marc Zyngier @ 2026-06-06 10:52 UTC (permalink / raw)
To: Hyunwoo Kim
Cc: tabba, oupton, joey.gouly, seiden, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm
In-Reply-To: <aiPfuAmM8JbtT6GY@v4bel>
On Sat, 06 Jun 2026 09:52:08 +0100,
Hyunwoo Kim <imv4bel@gmail.com> wrote:
>
> On Fri, Jun 05, 2026 at 09:58:09AM +0100, Marc Zyngier wrote:
> > On Thu, 04 Jun 2026 16:12:03 +0100,
> > Hyunwoo Kim <imv4bel@gmail.com> wrote:
> > >
> > > flush_hyp_vcpu() copies the host vGIC state into the hyp's private vCPU
> > > on every run. The vGIC list register save and restore use used_lrs as
> > > their loop bound and expect it to stay within the number of implemented
> > > list registers. While this is generally the case, flush_hyp_vcpu()
> > > copies vgic_v3 verbatim and does not enforce this, so a value provided
> > > by the host is used at EL2 to index vgic_lr[] and access ICH_LR<n>_EL2
> > > (host -> EL2).
> > >
> > > Fix by clamping used_lrs to the number of implemented list registers
> > > after the copy, as the trusted path already does in
> > > vgic_flush_lr_state().
> > >
> > > Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
> > > Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
> > > ---
> > > arch/arm64/kvm/hyp/nvhe/hyp-main.c | 8 ++++++++
> > > 1 file changed, 8 insertions(+)
> > >
> > > diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > > index 02c5d6e5abcbf..cd807fdb11ba8 100644
> > > --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > > +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > > @@ -7,6 +7,7 @@
> > > #include <hyp/adjust_pc.h>
> > > #include <hyp/switch.h>
> > >
> > > +#include <asm/arch_gicv3.h>
> > > #include <asm/pgtable-types.h>
> > > #include <asm/kvm_asm.h>
> > > #include <asm/kvm_emulate.h>
> > > @@ -142,6 +143,13 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
> > >
> > > hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
> > >
> > > + /* Bound used_lrs by the number of implemented list registers. */
> > > + if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
> >
> > There is no pKVM support without a GICv3 CPU interface, and absolutely
> > everything already assumes it. Why do we need this extra check?
> >
> > > + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
> > > + min_t(unsigned int,
> > > + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
> > > + (read_gicreg(ICH_VTR_EL2) & 0xf) + 1);
> > > +
> >
> > Reading ICH_VTR_EL2 on each entry is going to cause some really heavy
> > trapping under NV, and we should avoid this.
> >
> > kvm_vgic_global_state.nr_lr contains this information, and it should
> > only be a matter of replicating it (or compute it once) at init time.
>
> Does this approach look reasonable to you?
>
> ---
>
> diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
> index 8d06b62e7188..25199769a1d6 100644
> --- a/arch/arm64/include/asm/kvm_hyp.h
> +++ b/arch/arm64/include/asm/kvm_hyp.h
> @@ -157,5 +157,6 @@ extern unsigned long kvm_nvhe_sym(__icache_flags);
> extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
> extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
> extern unsigned long kvm_nvhe_sym(hyp_nr_cpus);
> +extern unsigned int kvm_nvhe_sym(hyp_vgic_nr_lr);
>
> #endif /* __ARM64_KVM_HYP_H__ */
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 9453321ef8c6..891fe2c7b854 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -2426,6 +2426,7 @@ static int __init init_subsystems(void)
> switch (err) {
> case 0:
> vgic_present = true;
> + kvm_nvhe_sym(hyp_vgic_nr_lr) = kvm_vgic_global_state.nr_lr;
You probably want to guard this on kvm_vgic_global_state.gicv3_cpuif
to be sure this stays to 0 when running with a GICv2 implementation.
And maybe rename it to hyp_gicv3_nr_lr to avoid any confusion.
> break;
> case -ENODEV:
> case -ENXIO:
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 06db299c37a8..8bb9362bc284 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -128,6 +128,9 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
>
> hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt;
>
> + /* A guest context must keep a NULL __hyp_running_vcpu. */
> + hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
> +
> hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
> hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE);
> hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
> @@ -139,6 +142,12 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
>
> hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
>
> + /* Bound used_lrs by the number of implemented list registers. */
> + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
> + min_t(unsigned int,
> + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
> + hyp_vgic_nr_lr);
> +
> hyp_vcpu->vcpu.arch.pid = host_vcpu->arch.pid;
> }
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
> index d461981616d9..ebc6b4afc336 100644
> --- a/arch/arm64/kvm/hyp/nvhe/setup.c
> +++ b/arch/arm64/kvm/hyp/nvhe/setup.c
> @@ -20,6 +20,7 @@
> #include <nvhe/trap_handler.h>
>
> unsigned long hyp_nr_cpus;
> +unsigned int hyp_vgic_nr_lr;
You could probably move this close to the place where it is used
instead of an unrelated file.
Other than that, and with the vcpu-related hunk in its own patch, this
looks reasonable.
Thanks,
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply
* Re: [PATCH v2 2/2] KVM: arm64: Bound used_lrs when flushing the pKVM hyp vCPU
From: Hyunwoo Kim @ 2026-06-06 8:52 UTC (permalink / raw)
To: Marc Zyngier
Cc: tabba, oupton, joey.gouly, seiden, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm, imv4bel
In-Reply-To: <86zf19tlcu.wl-maz@kernel.org>
On Fri, Jun 05, 2026 at 09:58:09AM +0100, Marc Zyngier wrote:
> On Thu, 04 Jun 2026 16:12:03 +0100,
> Hyunwoo Kim <imv4bel@gmail.com> wrote:
> >
> > flush_hyp_vcpu() copies the host vGIC state into the hyp's private vCPU
> > on every run. The vGIC list register save and restore use used_lrs as
> > their loop bound and expect it to stay within the number of implemented
> > list registers. While this is generally the case, flush_hyp_vcpu()
> > copies vgic_v3 verbatim and does not enforce this, so a value provided
> > by the host is used at EL2 to index vgic_lr[] and access ICH_LR<n>_EL2
> > (host -> EL2).
> >
> > Fix by clamping used_lrs to the number of implemented list registers
> > after the copy, as the trusted path already does in
> > vgic_flush_lr_state().
> >
> > Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
> > Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
> > ---
> > arch/arm64/kvm/hyp/nvhe/hyp-main.c | 8 ++++++++
> > 1 file changed, 8 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > index 02c5d6e5abcbf..cd807fdb11ba8 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > @@ -7,6 +7,7 @@
> > #include <hyp/adjust_pc.h>
> > #include <hyp/switch.h>
> >
> > +#include <asm/arch_gicv3.h>
> > #include <asm/pgtable-types.h>
> > #include <asm/kvm_asm.h>
> > #include <asm/kvm_emulate.h>
> > @@ -142,6 +143,13 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
> >
> > hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
> >
> > + /* Bound used_lrs by the number of implemented list registers. */
> > + if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
>
> There is no pKVM support without a GICv3 CPU interface, and absolutely
> everything already assumes it. Why do we need this extra check?
>
> > + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
> > + min_t(unsigned int,
> > + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
> > + (read_gicreg(ICH_VTR_EL2) & 0xf) + 1);
> > +
>
> Reading ICH_VTR_EL2 on each entry is going to cause some really heavy
> trapping under NV, and we should avoid this.
>
> kvm_vgic_global_state.nr_lr contains this information, and it should
> only be a matter of replicating it (or compute it once) at init time.
Does this approach look reasonable to you?
---
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 8d06b62e7188..25199769a1d6 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -157,5 +157,6 @@ extern unsigned long kvm_nvhe_sym(__icache_flags);
extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits);
extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl);
extern unsigned long kvm_nvhe_sym(hyp_nr_cpus);
+extern unsigned int kvm_nvhe_sym(hyp_vgic_nr_lr);
#endif /* __ARM64_KVM_HYP_H__ */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 9453321ef8c6..891fe2c7b854 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2426,6 +2426,7 @@ static int __init init_subsystems(void)
switch (err) {
case 0:
vgic_present = true;
+ kvm_nvhe_sym(hyp_vgic_nr_lr) = kvm_vgic_global_state.nr_lr;
break;
case -ENODEV:
case -ENXIO:
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 06db299c37a8..8bb9362bc284 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -128,6 +128,9 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt;
+ /* A guest context must keep a NULL __hyp_running_vcpu. */
+ hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
+
hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE);
hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
@@ -139,6 +142,12 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
+ /* Bound used_lrs by the number of implemented list registers. */
+ hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
+ min_t(unsigned int,
+ hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
+ hyp_vgic_nr_lr);
+
hyp_vcpu->vcpu.arch.pid = host_vcpu->arch.pid;
}
diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index d461981616d9..ebc6b4afc336 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -20,6 +20,7 @@
#include <nvhe/trap_handler.h>
unsigned long hyp_nr_cpus;
+unsigned int hyp_vgic_nr_lr;
#define hyp_percpu_size ((unsigned long)__per_cpu_end - \
(unsigned long)__per_cpu_start)
>
> Thanks,
>
> M.
>
> --
> Without deviation from the norm, progress is not possible.
Best regards,
Hyunwoo Kim
^ permalink raw reply related
* Re: [PATCH bpf-next v2 8/8] selftests/bpf: add tests to validate KASAN on JIT programs
From: Alexis Lothoré @ 2026-06-06 8:51 UTC (permalink / raw)
To: Yonghong Song, Alexis Lothoré, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Song Liu, Jiri Olsa,
John Fastabend, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Shuah Khan, Maxime Coquelin,
Alexandre Torgue, Ihor Solodrai
Cc: ebpf, Bastien Curutchet, Thomas Petazzoni, bpf, linux-kernel,
linux-kselftest, linux-stm32, linux-arm-kernel
In-Reply-To: <d717e193-f3b3-4022-8b0f-5e94595dd69b@linux.dev>
On Sat Jun 6, 2026 at 6:09 AM CEST, Yonghong Song wrote:
[...]
>>> But when I am running another same test './test_progs -t kasan', there is no kasan reports.
>> Ok, I guess you are missing kasan_multi_shot on your kernel command
>> line: without this option, only the first report is generated, then
>> KASAN does not emit additional report until you restart your kernel.
>> Could you please try adding it and running the tests again ?
>
> Thanks! Adding 'kasan_multi_shot' to the kernel command line indeed fixed the problem.
> It would be great if you can mention 'kasan_multi_shot' is needed in kernel command
> line in cover letter and in patch 8.
Yes, that's definitely missing, I'll make sure to add it. Thanks again
for the test !
Alexis
--
Alexis Lothoré, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [RESEND,v2 1/2] dt-bindings: memory-controllers: mtk-smi: Add support for mt8189
From: Zhengnan Chen (陈征南) @ 2026-06-06 8:06 UTC (permalink / raw)
To: robh@kernel.org, matthias.bgg@gmail.com,
Yong Wu (吴勇), conor+dt@kernel.org, krzk@kernel.org,
AngeloGioacchino Del Regno
Cc: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
Congcong Yao (姚聪聪),
devicetree@vger.kernel.org, Project_Global_Chrome_Upstream_Group
In-Reply-To: <50e53fd9-4cca-4cac-9f8d-868de3a8a7bc@kernel.org>
On Sun, 2026-05-24 at 21:08 +0200, Krzysztof Kozlowski wrote:
> On 27/04/2026 09:04, mtk20898 wrote:
> > From: Zhengnan Chen <zhengnan.chen@mediatek.com>
> >
> > Add binding description for mt8189.
> >
> > The clocks number of mt8189 smi-sub common has a bit difference.
> > Its clock count is 2, while mt8195 has 3. Therefore, the minimum
> > number of clocks is changed to 2, with the third one being
> > optional.
>
> Then why does the binding say that mt8195 has two clocks? You already
> received exactly this question.
>
The MT8195 SMI_sub_common has always been designed with three clocks.
We have reviewed the HW design of the MT8189 SMI_sub_common and
confirmed that the MT8189 should also follow the MT8195's settings and
maintain a three-clock DTS configuration.
We will send out the next version as soon as possible.
> >
> > About what smi-sub-common is, please check the below diagram,
> > we add it in mediatek,smi-common.yaml file.
> >
> > Signed-off-by: Zhengnan Chen <zhengnan.chen@mediatek.com>
> > Reviewed-by: AngeloGioacchino Del Regno <
> > angelogioacchino.delregno@collabora.com>
>
>
> No need to resend this. You received comments at v2 and you should
> have
> implemented them.
>
OK, we will remove this in next version.
> Best regards,
> Krzysztof
^ permalink raw reply
* [PATCH net-next] net: airoha: simplify WAN device check in airoha_dev_init()
From: Lorenzo Bianconi @ 2026-06-06 7:05 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: linux-arm-kernel, linux-mediatek, netdev, Lorenzo Bianconi
airoha_register_gdm_devices() iterates eth->ports[] in order, so GDM2's
netdev is always registered before GDM3/GDM4. This means the explicit
check for eth->ports[1] && eth->ports[1]->devs[0] is a redundant
special-case of what airoha_get_wan_gdm_dev() already covers, since
GDM2 is always marked as WAN during its own ndo_init.
Remove the redundant check and rely solely on airoha_get_wan_gdm_dev()
which handles both the GDM2-present and GDM2-absent cases.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 5a8e84fa9918..b333a7b309c2 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2004,18 +2004,10 @@ static int airoha_dev_init(struct net_device *netdev)
switch (port->id) {
case AIROHA_GDM3_IDX:
- case AIROHA_GDM4_IDX: {
- struct airoha_eth *eth = dev->eth;
-
- /* GDM2 supports a single net_device */
- if (eth->ports[1] && eth->ports[1]->devs[0])
- break;
-
- if (airoha_get_wan_gdm_dev(eth))
+ case AIROHA_GDM4_IDX:
+ if (airoha_get_wan_gdm_dev(dev->eth))
break;
-
fallthrough;
- }
case AIROHA_GDM2_IDX:
/* GDM2 is always used as wan */
dev->flags |= AIROHA_PRIV_F_WAN;
---
base-commit: 903db046d5579bef0ea699eae4b279dd6455fc9f
change-id: 20260606-airoha-eth-simplify-dev-init-5d53c7cc004e
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* [PATCH net-next] net: airoha: add ethtool priv_flags support for LAN/WAN and GDM2 loopback
From: Lorenzo Bianconi @ 2026-06-06 6:30 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: linux-arm-kernel, linux-mediatek, netdev, Madhur Agrawal,
Lorenzo Bianconi
Introduce ethtool private flags infrastructure for the airoha ethernet
driver, allowing userspace to configure per-device behavior via ethtool.
Implement the "wan" private flag to let the user select whether a GDM
port is used as a hardware LAN or WAN interface. GDM2 is fixed as WAN
only, GDM1 is fixed as LAN only, while GDM3 and GDM4 can be switched
between LAN and WAN at runtime (when the interface is not running).
When a GDM3/GDM4 port is set to WAN mode, enable GDM2 loopback to
support hardware QoS. Conversely, when switching back to LAN mode,
disable the GDM2 loopback and restore the default forwarding
configuration.
Add airoha_disable_gdm2_loopback() as the counterpart of the existing
airoha_enable_gdm2_loopback(), and define FC_MAP6_DEF_VALUE for use
during loopback teardown.
Example usage to configure eth1 (GDM3/GDM4) as WAN:
$ ethtool --show-priv-flags eth1
Private flags for eth1:
wan: off
$ ethtool --set-priv-flags eth1 wan on
$ ethtool --show-priv-flags eth1
Private flags for eth1:
wan: on
To revert back to LAN mode:
$ ethtool --set-priv-flags eth1 wan off
Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 175 ++++++++++++++++++++++++++++++
drivers/net/ethernet/airoha/airoha_regs.h | 1 +
2 files changed, 176 insertions(+)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 5a8e84fa9918..487c5470fb01 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1960,6 +1960,45 @@ static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev)
return 0;
}
+static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev)
+{
+ struct airoha_eth *eth = dev->eth;
+ int i, src_port;
+ u32 pse_port;
+
+ src_port = eth->soc->ops.get_sport(dev->port, dev->nbq);
+ if (src_port < 0)
+ return src_port;
+
+ airoha_fe_clear(eth,
+ REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)),
+ SP_CPORT_MASK(src_port & SP_CPORT_DFT_MASK));
+
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
+ FE_PSE_PORT_DROP);
+ airoha_fe_clear(eth, REG_GDM_LPBK_CFG(AIROHA_GDM2_IDX),
+ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK);
+ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2
+ : FE_PSE_PORT_PPE1;
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
+ pse_port);
+
+ airoha_fe_rmw(eth, REG_FE_WAN_PORT, WAN0_MASK,
+ FIELD_PREP(WAN0_MASK, AIROHA_GDM2_IDX));
+
+ for (i = 0; i < eth->soc->num_ppe; i++)
+ airoha_fe_clear(eth, REG_PPE_DFT_CPORT(i, AIROHA_GDM2_IDX),
+ DFT_CPORT_MASK(AIROHA_GDM2_IDX));
+
+ /* Enable VIP and IFC for GDM2 */
+ airoha_fe_set(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));
+ airoha_fe_set(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));
+
+ airoha_fe_wr(eth, REG_SRC_PORT_FC_MAP6, FC_MAP6_DEF_VALUE);
+
+ return 0;
+}
+
static struct airoha_gdm_dev *
airoha_get_wan_gdm_dev(struct airoha_eth *eth)
{
@@ -2296,6 +2335,87 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+struct airoha_ethool_priv_flags {
+ char name[ETH_GSTRING_LEN];
+ int (*handler)(struct net_device *netdev, u32 flags);
+};
+
+static int airoha_dev_set_wan_flag(struct net_device *netdev, u32 flags)
+{
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
+
+ if (!((dev->flags ^ flags) & AIROHA_PRIV_F_WAN))
+ return 0;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ if (flags & AIROHA_PRIV_F_WAN) {
+ struct airoha_gdm_dev *wan_dev;
+
+ /* Verify the WAN device is not already configured */
+ wan_dev = airoha_get_wan_gdm_dev(eth);
+ if (wan_dev && wan_dev != dev)
+ return -EBUSY;
+
+ switch (port->id) {
+ case AIROHA_GDM2_IDX:
+ /* GDM2 can be used just as WAN */
+ return 0;
+ case AIROHA_GDM3_IDX:
+ case AIROHA_GDM4_IDX: {
+ int err;
+
+ dev->flags |= AIROHA_PRIV_F_WAN;
+ airoha_dev_set_qdma(dev);
+
+ err = airoha_enable_gdm2_loopback(dev);
+ if (err) {
+ dev->flags &= ~AIROHA_PRIV_F_WAN;
+ airoha_dev_set_qdma(dev);
+
+ return err;
+ }
+ break;
+ }
+ default:
+ /* GDM1 can be used just as LAN */
+ return -EOPNOTSUPP;
+ }
+ } else {
+ switch (port->id) {
+ case AIROHA_GDM2_IDX:
+ /* GDM2 can be used just as WAN */
+ return -EOPNOTSUPP;
+ case AIROHA_GDM3_IDX:
+ case AIROHA_GDM4_IDX: {
+ int err;
+
+ err = airoha_disable_gdm2_loopback(dev);
+ if (err)
+ return err;
+
+ dev->flags &= ~AIROHA_PRIV_F_WAN;
+ airoha_dev_set_qdma(dev);
+ break;
+ }
+ default:
+ /* GDM1 can be used just as LAN */
+ return 0;
+ }
+ }
+
+ return airoha_set_macaddr(dev, netdev->dev_addr);
+}
+
+static const struct airoha_ethool_priv_flags airoha_eth_priv_flags[] = {
+ { "wan", airoha_dev_set_wan_flag },
+};
+
+#define AIROHA_PRIV_FLAGS_STR_LEN ARRAY_SIZE(airoha_eth_priv_flags)
+
static void airoha_ethtool_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
{
@@ -2304,6 +2424,7 @@ static void airoha_ethtool_get_drvinfo(struct net_device *netdev,
strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver));
strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info));
+ info->n_priv_flags = AIROHA_PRIV_FLAGS_STR_LEN;
}
static void airoha_ethtool_get_mac_stats(struct net_device *netdev,
@@ -2368,6 +2489,56 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
} while (u64_stats_fetch_retry(&port->stats.syncp, start));
}
+static int airoha_ethtool_set_priv_flags(struct net_device *netdev, u32 flags)
+{
+ int i;
+
+ for (i = 0; i < AIROHA_PRIV_FLAGS_STR_LEN; i++) {
+ int err;
+
+ if (!airoha_eth_priv_flags[i].handler)
+ continue;
+
+ err = airoha_eth_priv_flags[i].handler(netdev, flags);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static u32 airoha_ethtool_get_priv_flags(struct net_device *netdev)
+{
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+
+ return dev->flags;
+}
+
+static int airoha_ethtool_get_sset_count(struct net_device *netdev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_PRIV_FLAGS:
+ return AIROHA_PRIV_FLAGS_STR_LEN;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void airoha_ethtool_get_strings(struct net_device *netdev,
+ u32 stringset, u8 *data)
+{
+ int i;
+
+ switch (stringset) {
+ case ETH_SS_PRIV_FLAGS:
+ for (i = 0; i < AIROHA_PRIV_FLAGS_STR_LEN; i++)
+ ethtool_puts(&data, airoha_eth_priv_flags[i].name);
+ break;
+ default:
+ break;
+ }
+}
+
static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
int channel, enum tx_sched_mode mode,
const u16 *weights, u8 n_weights)
@@ -3094,6 +3265,10 @@ static const struct ethtool_ops airoha_ethtool_ops = {
.get_rmon_stats = airoha_ethtool_get_rmon_stats,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.get_link = ethtool_op_get_link,
+ .set_priv_flags = airoha_ethtool_set_priv_flags,
+ .get_priv_flags = airoha_ethtool_get_priv_flags,
+ .get_sset_count = airoha_ethtool_get_sset_count,
+ .get_strings = airoha_ethtool_get_strings,
};
static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port)
diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
index 436f3c8779c1..4e17dfbcf2b8 100644
--- a/drivers/net/ethernet/airoha/airoha_regs.h
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
@@ -376,6 +376,7 @@
#define REG_SRC_PORT_FC_MAP6 0x2298
#define FC_ID_OF_SRC_PORT_MASK(_n) GENMASK(4 + ((_n) << 3), ((_n) << 3))
+#define FC_MAP6_DEF_VALUE 0x1b1a1918
#define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4
---
base-commit: 903db046d5579bef0ea699eae4b279dd6455fc9f
change-id: 20260606-airoha-ethtool-priv_flags-b6aa70caa780
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* [PATCH net-next] net: airoha: Use int instead of atomic_t for qdma users counter
From: Lorenzo Bianconi @ 2026-06-06 5:49 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: linux-arm-kernel, linux-mediatek, netdev, Lorenzo Bianconi
QDMA users counter is always accessed holding RTNL lock so we do not
require atomic_t for it.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 4 ++--
drivers/net/ethernet/airoha/airoha_eth.h | 3 +--
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 5a8e84fa9918..a5fe08864fa3 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1809,7 +1809,7 @@ static int airoha_dev_open(struct net_device *netdev)
airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
GLOBAL_CFG_TX_DMA_EN_MASK |
GLOBAL_CFG_RX_DMA_EN_MASK);
- atomic_inc(&qdma->users);
+ qdma->users++;
if (!airoha_is_lan_gdm_dev(dev) &&
airoha_ppe_is_enabled(qdma->eth, 1))
@@ -1863,7 +1863,7 @@ static int airoha_dev_stop(struct net_device *netdev)
REG_GDM_FWD_CFG(port->id),
FE_PSE_PORT_DROP);
- if (atomic_dec_and_test(&qdma->users)) {
+ if (!--qdma->users) {
airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
GLOBAL_CFG_TX_DMA_EN_MASK |
GLOBAL_CFG_RX_DMA_EN_MASK);
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index 8f42973f9cf5..e89c2dff411f 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -525,8 +525,7 @@ struct airoha_irq_bank {
struct airoha_qdma {
struct airoha_eth *eth;
void __iomem *regs;
-
- atomic_t users;
+ int users;
struct airoha_irq_bank irq_banks[AIROHA_MAX_NUM_IRQ_BANKS];
---
base-commit: 903db046d5579bef0ea699eae4b279dd6455fc9f
change-id: 20260606-airoha_qdma_users-no-atomic-0750cc2b42f1
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: [PATCH v3 1/3] dt-bindings: net: add Realtek r8169 family PCIe Ethernet
From: Ricardo Pardini @ 2026-06-06 5:03 UTC (permalink / raw)
To: Heiner Kallweit, nic_swsd, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: Sebastian Reichel, netdev, devicetree, linux-kernel,
linux-arm-kernel, linux-rockchip
In-Reply-To: <b7cc8eba-ff6e-417d-8e74-b3bb24e08a26@gmail.com>
On 05/06/2026 17:48, Heiner Kallweit wrote:
> On 05.06.2026 13:49, Ricardo Pardini via B4 Relay wrote:
>> From: Ricardo Pardini <ricardo@pardini.net>
>>
>> Add a binding for fixed/soldered Realtek PCIe Ethernet controllers
>> driven by the r8169 driver (RTL8125/8126/8127/8168 and variants).
>>
>> The "pciVVVV,DDDD" compatibles are the Open Firmware PCI Bus Binding
>> spelling, auto-derived from PCI-SIG vendor/device IDs, but they still
>> need a binding when used in a board DT - analogous to "usbVVVV,PPPP"
>> compatibles documented in their own bindings (e.g. microchip,lan95xx)
>> so board DTs attaching properties (fixed MAC, nvmem cell, ...) to
>> these PCI function nodes can be validated.
>>
>
> The of node seems to be created by of_pci_make_dev_node(). But this
> function is called for bridges only in pci_bus_add_device().
> So where is the node created in your case? Did you test node creation?
>
Hi Heiner,
Seems to me of_pci_make_dev_node() is not at play here - that's the
DT-synthesis path. For nodes already present in DT, the of_node is bound
earlier, during pci_setup_device() -> pci_set_of_node() ->
of_pci_find_child_device() via the 5-cell reg.
Ref testing: yes; with this series on a NanoPC-T6 I get, for example:
/sys/bus/pci/devices/0004:41:00.0/of_node ->
/sys/firmware/devicetree/base/pcie@fe190000/pcie@0,0/ethernet@0,0 and
u-boot correctly adds local-mac-address property there which is
correctly picked up kernel-side:
=> setenv eth1addr 8e:b4:90:66:66:66
=> boot
...
# readlink -f /sys/bus/pci/devices/0004:41:00.0/of_node
/sys/firmware/devicetree/base/pcie@fe190000/pcie@0,0/ethernet@0,0
# xxd /sys/bus/pci/devices/0004:41:00.0/of_node/local-mac-address
00000000: 8eb4 9066 6666 ...fff
# ip link show dev end1 | grep ether
link/ether 8e:b4:90:66:66:66 brd ff:ff:ff:ff:ff:ff
>> +properties:
>> + compatible:
>> + enum:
>> + - pci10ec,8125 # RTL8125 2.5GbE
>> + - pci10ec,8126 # RTL8126 5GbE
>> + - pci10ec,8127 # RTL8127
>> + - pci10ec,8161 # RTL8168 variant
>> + - pci10ec,8162 # RTL8168 variant
>> + - pci10ec,8168 # RTL8168/8111 GbE
>
> This list reflects just some of the PCI id's handled by r8169.
> Any specific reason for this exact selection?
I went for "chips likely to be soldered down on an SBC", but that was
indeed speculative.
I guess I should trim to pci10ec,8125, which is all this series
describes? (further IDs can be added by the patches that introduce
boards using them)
--
Regards,
Ricardo
^ permalink raw reply
* Re: [PATCH bpf-next v2 8/8] selftests/bpf: add tests to validate KASAN on JIT programs
From: Yonghong Song @ 2026-06-06 4:09 UTC (permalink / raw)
To: Alexis Lothoré, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Song Liu, Jiri Olsa, John Fastabend,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Shuah Khan, Maxime Coquelin, Alexandre Torgue,
Ihor Solodrai
Cc: ebpf, Bastien Curutchet, Thomas Petazzoni, bpf, linux-kernel,
linux-kselftest, linux-stm32, linux-arm-kernel
In-Reply-To: <DJ1EYKOXV11H.25EJOUKFI81T4@bootlin.com>
On 6/5/26 1:55 PM, Alexis Lothoré wrote:
> On Fri Jun 5, 2026 at 7:20 PM CEST, Yonghong Song wrote:
>
> [...]
>
>>> Are you seeing any kasan report when you manually check your kernel
>>> logs, or not at all ? If not at all, are you using the "CI" defconfig ?
>> I do see one report:
>>
>> [ 79.503059] ==================================================================
>> [ 79.503715] BUG: KASAN: slab-use-after-free in bpf_prog_bb753b2ee1f69aa0_st_not_on_stack+0x115/0x160
>> [ 79.503715] Write of size 1 at addr ff11000117210a20 by task test_progs/2153
>>
>> [ 79.503715] CPU: 6 UID: 0 PID: 2153 Comm: test_progs Tainted: G OE 7.1.0-rc5-gd552a156c2fa #1926 PREEMPT(full)
>> [ 79.503715] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
>> [ 79.503715] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
>> [ 79.503715] Call Trace:
>> [ 79.503715] <TASK>
>> [ 79.503715] dump_stack_lvl+0x6d/0xa0
>> [ 79.503715] print_address_description+0x77/0x200
>> [ 79.503715] print_report+0x58/0x70
>> [ 79.503715] ? bpf_prog_bb753b2ee1f69aa0_st_not_on_stack+0x115/0x160
>> [ 79.503715] kasan_report+0xa2/0xe0
>> [ 79.503715] ? bpf_prog_bb753b2ee1f69aa0_st_not_on_stack+0x115/0x160
>> [ 79.503715] ? bpf_test_run+0x208/0x770
>> [ 79.503715] bpf_prog_bb753b2ee1f69aa0_st_not_on_stack+0x115/0x160
>> [ 79.503715] bpf_test_run+0x472/0x770
>> [ 79.503715] ? srso_alias_return_thunk+0x5/0xfbef5
>> [ 79.503715] ? __lock_acquire+0xe4a/0x2a10
>> [ 79.503715] ? __pfx___css_rstat_updated+0x10/0x10
>> [ 79.503715] ? __lock_acquire+0xe4a/0x2a10
>> [ 79.503715] ? __pfx_bpf_test_run+0x10/0x10
>> [ 79.503715] ? srso_alias_return_thunk+0x5/0xfbef5
>> [ 79.503715] ? lock_acquire+0xfd/0x2b0
>> [ 79.503715] ? srso_alias_return_thunk+0x5/0xfbef5
>> [ 79.503715] ? srso_alias_return_thunk+0x5/0xfbef5
>> [ 79.503715] ? rcu_is_watching+0x1f/0xa0
>> [ 79.503715] ? srso_alias_return_thunk+0x5/0xfbef5
>> [ 79.503715] ? __kasan_krealloc+0xe9/0x110
>> [ 79.503715] ? eth_type_trans+0x4b9/0x5f0
>> [ 79.503715] bpf_prog_test_run_skb+0xddf/0x22f0
>> [ 79.503715] ? __fget_files+0x29/0x350
>> [ 79.503715] ? srso_alias_return_thunk+0x5/0xfbef5
>> [ 79.503715] ? __fget_files+0x29/0x350
>> [ 79.503715] bpf_prog_test_run+0x1cc/0x2d0
>> [ 79.503715] __sys_bpf+0x740/0xa30
>> [ 79.503715] ? __pfx___sys_bpf+0x10/0x10
>> [ 79.503715] ? _prb_read_valid+0x334/0x770
>> [ 79.503715] ? handle_mm_fault+0x91b/0xc00
>> [ 79.503715] __x64_sys_bpf+0xba/0xd0
>> [ 79.503715] do_syscall_64+0xee/0x400
>> [ 79.503715] ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
>> [ 79.503715] entry_SYSCALL_64_after_hwframe+0x76/0x7e
>> [ 79.503715] RIP: 0033:0x7f92d8cfe1ad
>> [ 79.503715] Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 8
>> [ 79.503715] RSP: 002b:00007ffe4237fee8 EFLAGS: 00000206 ORIG_RAX: 0000000000000141
>> [ 79.503715] RAX: ffffffffffffffda RBX: 00007ffe423807b8 RCX: 00007f92d8cfe1ad
>> [ 79.503715] RDX: 0000000000000050 RSI: 00007ffe4237ff70 RDI: 000000000000000a
>> [ 79.503715] RBP: 00007ffe4237ff10 R08: 0000000000000000 R09: 0000000000000050
>> [ 79.503715] R10: 0000000000000064 R11: 0000000000000206 R12: 0000000000000000
>> [ 79.503715] R13: 00007ffe423807d8 R14: 00007f92d8eb9000 R15: 00005585778dd150
>> [ 79.503715] </TASK>
>>
>> [ 79.503715] Allocated by task 2153:
>> [ 79.503715] kasan_save_track+0x2f/0x70
>> [ 79.503715] __kasan_kmalloc+0x72/0x90
>> [ 79.503715] __kmalloc_node_noprof+0x34c/0x730
>> [ 79.503715] bpf_map_area_alloc+0x4a/0x110
>> [ 79.503715] array_map_alloc+0x19e/0x580
>> [ 79.503715] map_create+0x8b2/0x1500
>> [ 79.503715] __sys_bpf+0x7ea/0xa30
>> [ 79.503715] __x64_sys_bpf+0xba/0xd0
>> [ 79.503715] do_syscall_64+0xee/0x400
>> [ 79.503715] entry_SYSCALL_64_after_hwframe+0x76/0x7e
>>
>> [ 79.503715] The buggy address belongs to the object at ff11000117210800
>> which belongs to the cache kmalloc-cg-1k of size 1024
>> [ 79.503715] The buggy address is located 0 bytes to the right of
>> freed 544-byte region [ff11000117210800, ff11000117210a20)
>>
>> [ 79.503715] The buggy address belongs to the physical page:
>> [ 79.503715] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x117210
>> [ 79.503715] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
>> [ 79.503715] memcg:ff11000117210411
>> [ 79.503715] flags: 0x200000000000040(head|node=0|zone=2)
>> [ 79.503715] page_type: f5(slab)
>> [ 79.503715] raw: 0200000000000040 ff11000100072000 dead000000000100 dead000000000122
>> [ 79.503715] raw: 0000000000000000 0000080000100010 00000000f5000000 ff11000117210411
>> [ 79.503715] head: 0200000000000040 ff11000100072000 dead000000000100 dead000000000122
>> [ 79.503715] head: 0000000000000000 0000080000100010 00000000f5000000 ff11000117210411
>> [ 79.503715] head: 0200000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
>> [ 79.503715] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000008
>> [ 79.503715] page dumped because: kasan: bad access detected
>>
>> [ 79.503715] Memory state around the buggy address:
>> [ 79.503715] ff11000117210900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>> [ 79.503715] ff11000117210980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>> [ 79.503715] >ff11000117210a00: 00 00 00 00 fb fb fc fc fc fc fc fc fc fc fc fc
>> [ 79.503715] ^
>> [ 79.503715] ff11000117210a80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>> [ 79.503715] ff11000117210b00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>> [ 79.503715] ==================================================================
>>
>>
>> But when I am running another same test './test_progs -t kasan', there is no kasan reports.
> Ok, I guess you are missing kasan_multi_shot on your kernel command
> line: without this option, only the first report is generated, then
> KASAN does not emit additional report until you restart your kernel.
> Could you please try adding it and running the tests again ?
Thanks! Adding 'kasan_multi_shot' to the kernel command line indeed fixed the problem.
It would be great if you can mention 'kasan_multi_shot' is needed in kernel command
line in cover letter and in patch 8.
>
> Thanks,
>
> Alexis
>
>>> cat tools/testing/selftests/bpf/{config,config.vm,config.x86_64} > .config && make olddefconfig
>>>
>>> If not, would you mind sharing your defconfig ?
>> Attached.
>>
>>> Thanks,
>>>
>>> Alexis
>
>
>
^ permalink raw reply
* [PATCH] ASoC: mediatek: mt8365: check suspend backup allocation
From: Ruoyu Wang @ 2026-06-06 4:07 UTC (permalink / raw)
To: Liam Girdwood
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Matthias Brugger,
AngeloGioacchino Del Regno, linux-sound, linux-kernel,
linux-arm-kernel, linux-mediatek, Ruoyu Wang
mt8365_afe_suspend() lazily allocates the register backup array and then
stores register values into it. If devm_kcalloc() fails, the suspend path
dereferences afe->reg_back_up in the backup loop.
Check the allocation result before using the array. Disable the main
clock before returning so the error path balances the clock enable at the
start of suspend.
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
---
sound/soc/mediatek/mt8365/mt8365-afe-pcm.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c
index d01793394f225..74e4f53b31605 100644
--- a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c
+++ b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c
@@ -1978,6 +1978,10 @@ static int mt8365_afe_suspend(struct device *dev)
afe->reg_back_up =
devm_kcalloc(dev, afe->reg_back_up_list_num,
sizeof(unsigned int), GFP_KERNEL);
+ if (!afe->reg_back_up) {
+ mt8365_afe_disable_main_clk(afe);
+ return -ENOMEM;
+ }
for (i = 0; i < afe->reg_back_up_list_num; i++)
regmap_read(regmap, afe->reg_back_up_list[i],
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v4 18/24] iommu/arm-smmu-v3: Introduce master->ats_broken flag
From: Nicolin Chen @ 2026-06-06 4:04 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <20260605230315.GF1962447@nvidia.com>
On Fri, Jun 05, 2026 at 08:03:15PM -0300, Jason Gunthorpe wrote:
> On Fri, Jun 05, 2026 at 02:56:06PM -0700, Nicolin Chen wrote:
> > On Fri, Jun 05, 2026 at 04:42:59PM -0300, Jason Gunthorpe wrote:
> > > I don't see any of these options as appealing. We have to maintain a
> > > few key invariants, and I think it cannot be done without a way to
> > > find all the domains that are using the STE.
> > >
> > > One way or another you have to be using the invs list rw locks to
> > > synchronize the EATS state changes.
> > >
> > > It is okayish to be sloppy when turning EATS off, but when turning it
> > > back on we do need to cycle through every invs list and toggle its
> > > lock to ensure that the invalidations are synchronized before
> > > EATS=enable happens.
> >
> > I think the core guarantees that "cycle through every invs list"
> > happens: a PCI reset calls reset_prepare() blocking all the RID
> > and PASID domains and removing ATS entries from every invs list,
> > and then calls reset_done() that re-attach RID/PASID domains so
> > freshly new ATS entries will be installed before EATS=enable.
>
> I think this whole thing is so async and racy this is not something we
> can truely rely on. The driver is going to have to make sure it
> doesn't get turned on accidentally while the CD is still populated.
You mean the driver needs to ensure that the ATS entires in the
invs list would not be skipped when STE.EATS is enabled, right?
Otherwise, INV_TYPE_ATS_BROKEN + per-master domain list cannot
prevent a concurrent attach() from turning on STE.EATS either.
> > > Given you must have a way to go from STE -> master -> all invs lists
> > > I'm not sure either option really makes such a large difference.
> > >
> > > If so then adjusting the invs to disable the ATS is pretty simple, run
> > > over the xarray and set them all off. Yes you could find the master
> > > through a SID lookup with some locking adjustment.
> > > >
> > > > (1) Per-invs marker: INV_TYPE_ATS_BROKEN + master_domains
> > > > disable_ats() in the timeout path walks master->master_domains
> > > > and flips matching ATS invs entries to the BROKEN type.
> > > >
> > > > + invs walker is free (one case label in the existing type switch).
> > > > + No lock or pointer deref in the invs walker.
> > > > + No master pointer stored in invs; no lifetime concern.
> > > >
> > > > - disable_ats() walks every (master, domain) and marks each invs
> > > > set; the list needs locking usable from atomic.
> > >
> > > This doesn't seem so bad
> >
> > Yea, the only thing is that the disable path has to deal with a
> > complexity from going through a per-device domain list. Maybe it
> > can reuse iommu_group->pasid_array by taking xa_lock?
>
> Maybe the locking seems tricky as the locks might end up nesting in
> weird ways.
Oh, that's thoughtful.
> The streams rb tree and existing master domains linked list seems
> appealing if the locking can nest acceptably.
Yea, limiting the locking at the driver-level is more manageable.
> > > > (3) Per-master flag + inv->master pointer (v4)
> > > > invs entry carries a master pointer; the invs walker reads
> > > > cur->master->ats_broken directly.
> > > >
> > > > + invs walker is one READ_ONCE through a cached pointer.
> > > > + disable_ats is one WRITE_ONCE.
> > > > + atc_inv_master early-skip via one READ_ONCE.
> > > > + attach gate + post-attach re-check, same as (2).
> > > >
> > > > - invs holds a master ptr, so release_device must synchronize_rcu()
> > > > before freeing the master to drain walkers under rcu_read_lock().
> > > > We dropped this from v4 for that reason.
> > >
> > > synchronize_rcu is not right because you have to have gone through the
> > > rwlock so there can be no readers.
> >
> > Ah, I think you are right! When release_device() is invoked, the
> > device must be already in the release (blocked) domain. So there
> > should be no domain->invs in the system holding its ATS entries.
> > And the enable part would work as (2).
> >
> > In this case, (3) seems the best? It's fast on every aspect.
>
> I don't like it mainly because of the sketch enable side, and if we
> tighten that then you can just do 1 which doesn't have a perf impact..
I agree that per-master flag alone would be racy. So, for it to
work, it would need an extra spinlock. This v4 actually added a
pairing ats_broken_lock to fence arm_smmu_write_entry() in the
attach path, while the quarantine path is disabling STE.EATS and
setting the per-master flag. With that, the driver can ensure:
- no race in STE.EATS update
- consistency between STE.EATS and ATS entries in every invs
> But still, I'm not sure how all the asyncess and races will resolve in
> any of these cases.
Maybe we can try "INV_TYPE_ATS_BROKEN + per-master domain list"
first and see if Sashiko might identify some corner case.
Thanks
Nicolin
^ permalink raw reply
* Re: [PATCH v3 0/5] remoteproc: cleanup shared carveout and resource-table helpers
From: Peng Fan @ 2026-06-06 3:43 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Ben Levinsky, arnaud.pouliquen, daniel.baluta, Bjorn Andersson,
linux-remoteproc, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Geert Uytterhoeven, Magnus Damm, Patrice Chotard,
Maxime Coquelin, Alexandre Torgue, Tanmay Shah, imx,
linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32
In-Reply-To: <ah2aVdlsLqy9aeHP@p14s>
On Mon, Jun 01, 2026 at 08:42:29AM -0600, Mathieu Poirier wrote:
>Good morning,
>
>On Thu, May 28, 2026 at 07:16:32PM -0700, Ben Levinsky wrote:
>> This series is a preparatory remoteproc cleanup split out from review of
>> the AMD BRAM-based remoteproc series.
>>
>> During review, there was a request to move the duplicated plain
>> ioremap_wc()/iounmap() carveout callbacks into common code and to
>> factor the "missing resource table is OK" ELF parsing path into a
>> common helper as well. There was also a request to send that cleanup as
>> its own patchset first, with the AMD BRAM series respun afterwards on
>> top once this cleanup is merged.
>>
>> This version keeps the same overall cleanup goals as v2, but reworks
>> the optional resource-table pieces based on follow-up review:
>>
>> - reshape the optional resource-table helper in patch 4 into the thin
>> parse_fw() wrapper form suggested on the thread
>> - switch the patch 5 clients over to that helper shape directly,
>> without post-helper rproc->table_ptr checks
>> - keep the driver-local parse_fw() wrappers and their existing log
>> messages and severity choices
>> - retain as much of the existing per-driver parse_fw() logic and code
>> placement as possible while moving the missing-table handling
>> through the shared helper
>>
>> This series now does that in five patches:
>>
>> 1. add common subsystem-private callbacks for the exact-match
>> wc-ioremap carveout case
>> 2. switch the in-tree exact-match users over to those callbacks
>> 3. mark carveouts mapped through the shared wc-ioremap helper as
>> iomem so the framework uses the proper I/O accessors
>> 4. add a common helper for drivers that treat a missing ELF resource
>> table as optional while keeping per-driver logging decisions local
>> 5. switch the matching in-tree drivers over to that helper while
>> keeping thin local parse_fw() wrappers
>>
>> For the carveout map/unmap cleanup, this series covers the exact-match
>> users called out in review: xlnx_r5_remoteproc, rcar_rproc,
>> st_remoteproc, stm32_rproc, imx_rproc, and imx_dsp_rproc. The zynqmp R5
>> TCM mapping path is left alone because it also clears the mapped memory
>> and is not an exact match.
>>
>> For the optional resource-table handling, this series converts
>> xlnx_r5_remoteproc, rcar_rproc, stm32_rproc, imx_rproc, and
>> imx_dsp_rproc. st_remoteproc is intentionally left unchanged because its
>> parse_fw() callback also builds carveouts and is therefore not a direct
>> match for the helper introduced here.
>>
>> Changes in v3:
>> - rework patch 4 so the optional resource-table helper matches the
>> thin-wrapper form suggested in review
>> - note that patch 4 still triggers a checkpatch --strict warning for
>> the flow-control macro form, but that implementation follows the
>> maintainer's review suggestion for the thin parse_fw() wrapper shape
>> - update patch 5 to use that helper shape directly in the client
>> parse_fw() callbacks
>> - drop the post-helper rproc->table_ptr checks from the converted
>> drivers
>> - keep the converted parse_fw() wrappers otherwise close to their
>> existing structure and placement
>> - test xlnx_r5_remoteproc on the latest tree with firmware images
>> both with and without an ELF resource table
>>
>> Changes in v2:
>> - split the mem->is_iomem change out into a separate patch
>> - add a common error message on ioremap_wc() failure
>> - drop logging from the optional resource-table helper
>> - keep driver-local parse_fw() wrappers to preserve per-platform
>> missing-resource-table logging policy
>>
>> Ben Levinsky (5):
>> remoteproc: add common wc-ioremap carveout callbacks
>> remoteproc: switch exact-match drivers to wc-ioremap callbacks
>> remoteproc: mark wc-ioremap carveouts as iomem
>> remoteproc: add helper for optional ELF resource tables
>> remoteproc: switch drivers to optional resource-table helper
>>
>> drivers/remoteproc/imx_dsp_rproc.c | 41 +++-----------
>> drivers/remoteproc/imx_rproc.c | 40 ++------------
>> drivers/remoteproc/rcar_rproc.c | 41 ++------------
>> drivers/remoteproc/remoteproc_internal.h | 38 +++++++++++++
>> drivers/remoteproc/st_remoteproc.c | 31 +----------
>> drivers/remoteproc/stm32_rproc.c | 39 ++-----------
>> drivers/remoteproc/xlnx_r5_remoteproc.c | 70 +++++-------------------
>
>This set looks good to me. I am fine with the checkpatch warning on the macro -
>given the redundancy it avoids, I think it can be tolerated.
>
>Wolfram has already indicated he wanted to test these changes - Arnaud, Daniel
>and Peng, please do the same for your platforms.
Tested-by: Peng Fan <peng.fan@nxp.com> #i.MX8MP-EVK
>
>Thanks,
>Mathieu
>
>> 7 files changed, 73 insertions(+), 227 deletions(-)
>>
>> --
>> 2.34.1
^ permalink raw reply
* [STATUS] arm64/for-kernelci - ffe7bef3786c1c2a725f80c2025010644452fd1c
From: KernelCI bot @ 2026-06-06 2:30 UTC (permalink / raw)
To: kernelci-results; +Cc: will, linux-arm-kernel
Hello,
Status summary for arm64/for-kernelci
Dashboard:
https://d.kernelci.org/c/arm64/for-kernelci/ffe7bef3786c1c2a725f80c2025010644452fd1c/
giturl: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
branch: for-kernelci
commit hash: ffe7bef3786c1c2a725f80c2025010644452fd1c
origin: maestro
test start time: 2026-06-05 17:03:21.134000+00:00
Builds: 8 ✅ 0 ❌ 0 ⚠️
Boots: 12 ✅ 0 ❌ 1 ⚠️
Tests: 10548 ✅ 84 ❌ 93 ⚠️
### POSSIBLE REGRESSIONS
No possible regressions observed.
### FIXED REGRESSIONS
No fixed regressions observed.
### UNSTABLE TESTS
Hardware: bcm2711-rpi-4-b
> Config: defconfig+lab-setup+kselftest
- Architecture/compiler: arm64/gcc-14
- boot
last run: https://d.kernelci.org/test/maestro:6a230ad146e71b76f9f6eb2e
history: > ⚠️ > ✅ > ✅ > ✅ > ⚠️
Sent every day if there were changes in the past 24 hours.
Legend: ✅ PASS ❌ FAIL ⚠️ INCONCLUSIVE
--
This is an experimental report format. Please send feedback in!
Talk to us at kernelci@lists.linux.dev
Made with love by the KernelCI team - https://kernelci.org
^ permalink raw reply
* Re: [PATCH] net: stmmac: xgmac: report L3/L4 filter match count in ethtool stats
From: patchwork-bot+netdevbpf @ 2026-06-06 2:20 UTC (permalink / raw)
To: Nazle, Asmade, Muhammad Nazim Amirul
Cc: netdev, andrew+netdev, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, alexandre.torgue, rmk+kernel, maxime.chevallier,
linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <20260604083037.24407-1-muhammad.nazim.amirul.nazle.asmade@altera.com>
Hello:
This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 4 Jun 2026 01:30:37 -0700 you wrote:
> From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
>
> Read the L3FM and L4FM bits from the RX descriptor status word (RDES2)
> and increment the corresponding ethtool statistics counters. This allows
> users to observe L3/L4 filter hit rates via ethtool -S.
>
> Signed-off-by: Rohan G Thomas <rohan.g.thomas@altera.com>
> Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
>
> [...]
Here is the summary with links:
- net: stmmac: xgmac: report L3/L4 filter match count in ethtool stats
https://git.kernel.org/netdev/net-next/c/903db046d557
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net-next v3] net: microchip: sparx5: clean up PSFP resources on flower setup failure
From: patchwork-bot+netdevbpf @ 2026-06-06 2:10 UTC (permalink / raw)
To: Haoxiang Li
Cc: andrew+netdev, davem, kuba, pabeni, Steen.Hegelund, daniel.machon,
UNGLinuxDriver, kees, netdev, linux-arm-kernel, linux-kernel
In-Reply-To: <20260603061716.747282-1-lihaoxiang@isrc.iscas.ac.cn>
Hello:
This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 3 Jun 2026 14:17:16 +0800 you wrote:
> sparx5_tc_flower_psfp_setup() allocates PSFP stream gate, flow meter and
> stream filter resources before adding VCAP actions. If a later step
> fails, the resources allocated earlier in the function are not unwound.
>
> Add error paths to release the stream filter, flow meter and stream gate
> when setup fails after they have been acquired.
>
> [...]
Here is the summary with links:
- [net-next,v3] net: microchip: sparx5: clean up PSFP resources on flower setup failure
https://git.kernel.org/netdev/net-next/c/46e503673387
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net-next v9 0/6] net: airoha: Support multiple net_devices connected to the same GDM port
From: patchwork-bot+netdevbpf @ 2026-06-06 2:10 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, robh, krzk+dt,
conor+dt, ansuelsmth, benjamin.larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, xuegang.lu, madhur.agrawal
In-Reply-To: <20260603-airoha-eth-multi-serdes-v9-0-5d476bc2f426@kernel.org>
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 03 Jun 2026 08:00:14 +0200 you wrote:
> EN7581 or AN7583 SoCs support connecting multiple external SerDes (e.g.
> Ethernet or USB SerDes) to GDM3 or GDM4 ports via a hw arbiter that
> manages the traffic in a TDM manner. As a result multiple net_devices can
> connect to the same GDM{3,4} port and there is a theoretical "1:n"
> relation between GDM ports and net_devices.
>
> ┌─────────────────────────────────┐
> │ │ ┌──────┐
> │ P1 GDM1 ├────►MT7530│
> │ │ └──────┘
> │ │ ETH0 (DSA conduit)
> │ │
> │ PSE/FE │
> │ │
> │ │
> │ │ ┌─────┐
> │ P0 CDM1 ├────►QDMA0│
> │ P4 P9 GDM4 │ └─────┘
> └──┬─────────────────────────┬────┘
> │ │
> ┌──▼──┐ ┌────▼────┐
> │ PPE │ │ ARB │
> └─────┘ └─┬─────┬─┘
> │ │
> ┌──▼──┐┌─▼───┐
> │ ETH ││ USB │
> └─────┘└─────┘
> ETH1 ETH2
>
> [...]
Here is the summary with links:
- [net-next,v9,1/6] dt-bindings: net: airoha: Add GDM port ethernet child node
https://git.kernel.org/netdev/net-next/c/a4597204b681
- [net-next,v9,2/6] net: airoha: Remove private net_device pointer in airoha_gdm_dev struct
https://git.kernel.org/netdev/net-next/c/4408f5206809
- [net-next,v9,3/6] net: airoha: Support multiple net_devices for a single FE GDM port
https://git.kernel.org/netdev/net-next/c/a9c2ca61fec7
- [net-next,v9,4/6] net: airoha: Do not stop GDM port if it is shared
https://git.kernel.org/netdev/net-next/c/99b9d095d71e
- [net-next,v9,5/6] net: airoha: Introduce WAN device flag
https://git.kernel.org/netdev/net-next/c/7758cb462ff7
- [net-next,v9,6/6] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration
https://git.kernel.org/netdev/net-next/c/ef2aee987174
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox