From nobody Mon Sep 28 21:52:48 2026 Received: from mail-pj1-f45.google.com (mail-pj1-f45.google.com [209.85.216.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E7D630568B for ; Mon, 17 Aug 2026 01:38:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786930682; cv=none; b=HJ192Apqhp5HwcfJ6UoYsg1AvlTEgynqyn01QrAA3LXj7GdhCnnhQcAOqP8Ltoic5LImgpkFY6mnHVcg8PbYklxBIXMIL7T5sGwkbBx8bG8vOWVOE47HnRIiV8l21+LO5YnuICA/RW5aygHof7NzxitOBjJ1Aa7yu2qCETyvEv8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786930682; c=relaxed/simple; bh=WGZhX3UNcSru063oe0/KPOEzdlRjCev1RZjHtYjB1g8=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=cjIjt2WzvFknqB0ZU6Nbo3P6nYicpLMUjtHNJCjdU/DREZ7sYUDFlrMZaUYNDigelrg+cTL70fQm0n1OcmcLyLUoBtpeaNXrq/FBg08MQrP7ycFWSDmnyP3ZOaIFgkUGnLzFtQ0WPUsFgoA/qF3SYsG9qrGUOpyMFYkuAgVh+q8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=qkuDeXow; arc=none smtp.client-ip=209.85.216.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qkuDeXow" Received: by mail-pj1-f45.google.com with SMTP id 98e67ed59e1d1-38f620399a0so2461417a91.2 for ; Sun, 16 Aug 2026 18:38:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786930679; x=1787535479; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=eY8RYhguruvb++TRBB7XQhOx6d1wihTPxhfFylErixw=; b=qkuDeXowmk3gWc3wF44DlHxFGXuuE7FyKsA7tAfDvSwPHlmYvP256iynWaFs5SsGSt QOkVRcqV9y2celUDvb1Cn8aZBj5iQ3MTh/6NM5Dz5z5JMJgptIa6L1z8j44b0aKjeI/l 4A4o3fgXRXhkgKzAyJ/G5slBdRBT1wPzQDhy7rNMOzQiLtocQ/MsxjnjWgGpixrMMsLB WeMabSXi4HJtwiVO+YddUd8xaXSLlW2r3iOunGh983/E/xFWJ6IxfPEorVM/19uW9cHB pe8SITuuiQB2pVWabWNmPKg56ZD3XD1NQxJzcCI7AJRadIRMR6FBQNvHNF8/V04jskd1 I2SQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786930679; x=1787535479; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=eY8RYhguruvb++TRBB7XQhOx6d1wihTPxhfFylErixw=; b=aZIFKnBPFl4amk4SpZdqrDT/z4g5OuDCvTfp+HU65DCk+uq26CVubC1L3r541tAJ/5 P38Y1hEHwvP3N4Byh3l91SG5y6+Cu7LEj9Ms/5AODDgO+6+EgzOV7JTdJXptjHCf6mBa PbcfmQj0YKmLwGF3qGY2x5Y3OicXtmfAKd/Tx7nGeotSr0J6o29EyeoFGpwLui98+vrP rO+/3FYqlqLkGwo+EMRzCHJbUivP/KhHxld7Tz5hGHPPX3PGEsT5vSqkbb3pw9rgTsR2 3BKJeH0bzp+7rqfdeFJhOA44bJudeYZNIoEuFwUGc0JVE4OkwRtOQ9U8nOb3BC9FConO uLUA== X-Forwarded-Encrypted: i=1; AHgh+RoJ5QvkLR+FFP/aDaBGPgYJYCzvD71ZewW3Ir4VkTux1UWowXwnlW3F3cU+cRoy5gF67oiCuIx+GEmmqsQ=@vger.kernel.org X-Gm-Message-State: AOJu0YyCews7AjHCuXHRis7EblyLmg0R/A6NvjEUXVeMtZIxlkGuy0Gs VjXs8BO/1/dGo7tCWQvmC+EjCcoUWFCjElrGFk7Sw1XjO1eLspyVYAH1 X-Gm-Gg: AR+sD13BlpcGYsgnGh7/TKvzNfNUhGPht6IWP3OyJZeObmY6iw045av8hOD/tC3r81R /zvIvGDo6Y8Uz9Gn7RqsIO7CPrBUCHEht79/Wsy9ex9Lt/gCSO+JHVDw74cJaAlRL4JvY04+ZlV 3KJWq5g2e/qJ+X815bqKbYIO8/HFhOwY3UOw5P1vXvaOpHRU2QROaZ99+vklc1j/u/8IFjnWjXn wiFc06VM+UpWdxkR9Vqbz7d3n9gvliXfru9khhf1iGqC+DyL8vmQWPvCIrLVQyZN/oiJ1DsOzf8 c8OIcF4o4NJznRjmZuI+ET1ll+vfwZ7UJpycPLrrsLBsGBW5gEGIhjPKINoIEhjs7gObb0Ts7sG ErXdtuNo44+Vvv0Hna07s1RhQcB/p08j0BqQUMujKcc0zjnGpADx8rlhuX48QQmLDxUPEhG6Bhh YcTethsqpBU0AHX9XbokLLnzkCqIrPr/cr9Q0R2+QMLwkGNWcXaoZaopwkXQKKA9AQmGxY8FQ3 X-Received: by 2002:a17:90b:224a:b0:38f:837e:fc5d with SMTP id 98e67ed59e1d1-3933b786507mr20975985a91.3.1786930679299; Sun, 16 Aug 2026 18:37:59 -0700 (PDT) Received: from localhost.localdomain ([120.236.7.85]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3954d3d2adcsm222657a91.17.2026.08.16.18.37.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Aug 2026 18:37:58 -0700 (PDT) From: Cheng Liu To: Marc Kleine-Budde , Wolfgang Grandegger Cc: linux-can@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Elaine Zhang , Cheng Liu Subject: [PATCH can] can: rockchip: rk3576: fix rtnl_lock deadlock during interface down under bus traffic Date: Mon, 17 Aug 2026 09:37:50 +0800 Message-Id: <20260817013750.1836064-1-chengliu480@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When bringing the CAN interface down (via `ip link set can0 down`) while there is heavy incoming CAN traffic or continuous hardware error frames, the system hangs and deadlocks. Existing and new networking operations (such as `ifconfig`, SSH logins, Socket operations) hang indefinitely waiting for `rtnl_lock`. The deadlock occurs because `rk3576_canfd_close()` calls `napi_disable()` before `rk3576_canfd_stop()`. Since hardware interrupts are still active, incoming CAN frames and error interrupts continuously trigger `napi_schedule()`, preventing `napi_disable()` from seeing the `NAPI_STATE_SCHED` bit cleared and causing it to loop infinitely in `msleep(1)`. Because `dev_close()` holds the global `rtnl_lock`, the entire networking subsystem deadlocks: Call trace: __switch_to+0xdc/0x120 __schedule+0x2ac/0x840 schedule+0x54/0xe0 schedule_hrtimeout_range_clock+0x98/0x134 usleep_range_state+0x7c/0xb0 napi_disable+0xc0/0x110 rk3576_canfd_close+0x44/0xd0 __dev_close_many+0xb0/0x14c dev_change_flags+0x28/0x64 do_setlink+0x618/0xe2c rtnetlink_rcv_msg+0x2a8/0x380 Fix this by: 1. Reordering `rk3576_canfd_close()` to call `rk3576_canfd_stop()` before `napi_disable()`, ensuring interrupts are disabled and controller is in reset mode before waiting for NAPI to complete. 2. Standardizing `rk3576_canfd_rx_poll()` to respect the NAPI quota/budget and properly complete NAPI polling via `napi_complete_done()`. 3. Guarding against NULL pointer dereference in `rk3576_canfd_err()` when `alloc_can_err_skb()` fails, and calling `can_bus_off()` upon bus-off. Signed-off-by: Cheng Liu --- drivers/net/can/rockchip/rk3576_canfd.c | 61 +++++++++++++------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/drivers/net/can/rockchip/rk3576_canfd.c b/drivers/net/can/rock= chip/rk3576_canfd.c index 2c0d7f056..d0f581bce 100644 --- a/drivers/net/can/rockchip/rk3576_canfd.c +++ b/drivers/net/can/rockchip/rk3576_canfd.c @@ -859,31 +859,28 @@ static int rk3576_canfd_rx_poll(struct napi_struct *n= api, int quota) { struct net_device *ndev =3D napi->dev; struct rk3576_canfd *rcan =3D netdev_priv(ndev); - int work_done =3D 0, cnt =3D 0; + int work_done =3D 0; + u32 frames_avail; =20 if (rcan->use_dma) { - while (work_done < rcan->quota) + while (work_done < rcan->quota && work_done < quota) work_done +=3D rk3576_canfd_rx(ndev, work_done); =20 - if (work_done <=3D rcan->rx_fifo_depth) { - napi_complete_done(napi, work_done); - rk3576_canfd_write(rcan, CANFD_INT_MASK, INT_ENABLE); + if (work_done < quota) { + if (napi_complete_done(napi, work_done)) + rk3576_canfd_write(rcan, CANFD_INT_MASK, INT_ENABLE); } } else { - quota =3D (rk3576_canfd_read(rcan, CANFD_STR_STATE) & rcan->rx_fifo_mask= ) >> - rcan->rx_fifo_shift; - quota =3D quota / rcan->rx_max_data; - cnt =3D (rk3576_canfd_read(rcan, CANFD_STR_STATE) & INTM_CNT_MASK) >> IN= TM_CNT_SHIFT; - if (quota !=3D cnt) - quota =3D ((rk3576_canfd_read(rcan, CANFD_STR_STATE) & rcan->rx_fifo_ma= sk) >> - rcan->rx_fifo_shift) / rcan->rx_max_data; - - while (work_done < quota) + frames_avail =3D (rk3576_canfd_read(rcan, CANFD_STR_STATE) & rcan->rx_fi= fo_mask) >> + rcan->rx_fifo_shift; + frames_avail =3D frames_avail / rcan->rx_max_data; + + while (work_done < frames_avail && work_done < quota) work_done +=3D rk3576_canfd_rx(ndev, CANFD_RXFRD); =20 - if (work_done <=3D rcan->rx_fifo_depth) { - napi_complete_done(napi, work_done); - rk3576_canfd_write(rcan, CANFD_INT_MASK, INT_ENABLE); + if (work_done < quota) { + if (napi_complete_done(napi, work_done)) + rk3576_canfd_write(rcan, CANFD_INT_MASK, INT_ENABLE); } } return work_done; @@ -926,7 +923,7 @@ static int rk3576_canfd_err(struct net_device *ndev, u3= 2 isr) { struct rk3576_canfd *rcan =3D netdev_priv(ndev); struct net_device_stats *stats =3D &ndev->stats; - struct can_frame *cf; + struct can_frame *cf =3D NULL; struct sk_buff *skb; unsigned int rxerr, txerr; u32 sta_reg; @@ -945,17 +942,21 @@ static int rk3576_canfd_err(struct net_device *ndev, = u32 isr) if (isr & BUS_OFF_INT) { rcan->can.state =3D CAN_STATE_BUS_OFF; rcan->can.can_stats.bus_off++; - cf->can_id |=3D CAN_ERR_BUSOFF; + can_bus_off(ndev); + if (skb) + cf->can_id |=3D CAN_ERR_BUSOFF; } else if (isr & PASSIVE_ERR_INT) { rcan->can.can_stats.error_passive++; rcan->can.state =3D CAN_STATE_ERROR_PASSIVE; /* error passive state */ - cf->can_id |=3D CAN_ERR_CRTL; - cf->data[1] =3D (txerr > rxerr) ? - CAN_ERR_CRTL_TX_WARNING : - CAN_ERR_CRTL_RX_WARNING; - cf->data[6] =3D txerr; - cf->data[7] =3D rxerr; + if (skb) { + cf->can_id |=3D CAN_ERR_CRTL; + cf->data[1] =3D (txerr > rxerr) ? + CAN_ERR_CRTL_TX_WARNING : + CAN_ERR_CRTL_RX_WARNING; + cf->data[6] =3D txerr; + cf->data[7] =3D rxerr; + } } if (sta_reg & ERR_WARNING_STATE) { rcan->can.can_stats.error_warning++; @@ -984,9 +985,11 @@ static int rk3576_canfd_err(struct net_device *ndev, u= 32 isr) can_free_echo_skb(ndev, 0, NULL); netif_start_queue(ndev); } - stats->rx_packets++; - stats->rx_bytes +=3D cf->can_dlc; - netif_rx(skb); + if (skb) { + stats->rx_packets++; + stats->rx_bytes +=3D cf->can_dlc; + netif_rx(skb); + } =20 return 0; } @@ -1070,8 +1073,8 @@ static int rk3576_canfd_close(struct net_device *ndev) struct rk3576_canfd *rcan =3D netdev_priv(ndev); =20 netif_stop_queue(ndev); - napi_disable(&rcan->napi); rk3576_canfd_stop(ndev); + napi_disable(&rcan->napi); close_candev(ndev); pm_runtime_put(rcan->dev); =20 --=20 2.34.1