]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Aug 2026 13:49:48 +0000 (15:49 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Aug 2026 13:49:48 +0000 (15:49 +0200)
added patches:
can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch
can-use-skb-hash-instead-of-private-variable-in-headroom.patch
ceph-fix-refcount-leak-in-ceph_readdir.patch
ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch
drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch
drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch
drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch
drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch
drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch
drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch
drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch
libceph-add-doutc-and-_client-debug-macros-support.patch
media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch
media-i2c-imx219-calculate-crop-rectangle-dynamically.patch
media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch
media-i2c-imx219-drop-imx219_vts_-macros.patch
media-i2c-imx219-group-functions-by-purpose.patch
media-i2c-imx219-rename-vts-to-frm_length.patch
media-imx219-fix-maximum-frame-length-in-lines.patch
media-v4l-async-set-owner-for-async-sub-devices.patch
media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch
mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch
mptcp-pm-avoid-code-duplication-to-lookup-endp.patch
mptcp-pm-use-addr-entry-for-get_local_id.patch
mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch
netfilter-nf_tables-clone-set-on-flush-only.patch
rxrpc-fix-irq-disabled-in-local_bh_enable.patch
sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch
sctp-close-udp-tunnel-sockets-during-netns-teardown.patch
sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch
usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch
usb-musb-omap2430-clean-up-probe-error-handling.patch
usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch
usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch
usb-typec-ucsi-only-enable-supported-notifications.patch
usb-typec-ucsi-split-connector-lock-classes.patch
wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch
wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch
wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch
wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch

41 files changed:
queue-6.6/can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch [new file with mode: 0644]
queue-6.6/can-use-skb-hash-instead-of-private-variable-in-headroom.patch [new file with mode: 0644]
queue-6.6/ceph-fix-refcount-leak-in-ceph_readdir.patch [new file with mode: 0644]
queue-6.6/ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch [new file with mode: 0644]
queue-6.6/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch [new file with mode: 0644]
queue-6.6/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch [new file with mode: 0644]
queue-6.6/drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch [new file with mode: 0644]
queue-6.6/drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch [new file with mode: 0644]
queue-6.6/drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch [new file with mode: 0644]
queue-6.6/drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch [new file with mode: 0644]
queue-6.6/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch [new file with mode: 0644]
queue-6.6/libceph-add-doutc-and-_client-debug-macros-support.patch [new file with mode: 0644]
queue-6.6/media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch [new file with mode: 0644]
queue-6.6/media-i2c-imx219-calculate-crop-rectangle-dynamically.patch [new file with mode: 0644]
queue-6.6/media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch [new file with mode: 0644]
queue-6.6/media-i2c-imx219-drop-imx219_vts_-macros.patch [new file with mode: 0644]
queue-6.6/media-i2c-imx219-group-functions-by-purpose.patch [new file with mode: 0644]
queue-6.6/media-i2c-imx219-rename-vts-to-frm_length.patch [new file with mode: 0644]
queue-6.6/media-imx219-fix-maximum-frame-length-in-lines.patch [new file with mode: 0644]
queue-6.6/media-v4l-async-set-owner-for-async-sub-devices.patch [new file with mode: 0644]
queue-6.6/media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch [new file with mode: 0644]
queue-6.6/mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch [new file with mode: 0644]
queue-6.6/mptcp-pm-avoid-code-duplication-to-lookup-endp.patch [new file with mode: 0644]
queue-6.6/mptcp-pm-use-addr-entry-for-get_local_id.patch [new file with mode: 0644]
queue-6.6/mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch [new file with mode: 0644]
queue-6.6/netfilter-nf_tables-clone-set-on-flush-only.patch [new file with mode: 0644]
queue-6.6/rxrpc-fix-irq-disabled-in-local_bh_enable.patch [new file with mode: 0644]
queue-6.6/sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch [new file with mode: 0644]
queue-6.6/sctp-close-udp-tunnel-sockets-during-netns-teardown.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch [new file with mode: 0644]
queue-6.6/usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch [new file with mode: 0644]
queue-6.6/usb-musb-omap2430-clean-up-probe-error-handling.patch [new file with mode: 0644]
queue-6.6/usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-only-enable-supported-notifications.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-split-connector-lock-classes.patch [new file with mode: 0644]
queue-6.6/wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch [new file with mode: 0644]
queue-6.6/wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch [new file with mode: 0644]
queue-6.6/wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch [new file with mode: 0644]
queue-6.6/wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch [new file with mode: 0644]

diff --git a/queue-6.6/can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch b/queue-6.6/can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch
new file mode 100644 (file)
index 0000000..a56198a
--- /dev/null
@@ -0,0 +1,746 @@
+From stable+bounces-297168-greg=kroah.com@vger.kernel.org Fri Aug  7 09:48:49 2026
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+Date: Fri,  7 Aug 2026 09:47:57 +0200
+Subject: can: isotp: fix timer drain order, wakeup handling and tx_gen ordering
+To: stable@vger.kernel.org
+Cc: Oliver Hartkopp <socketcan@hartkopp.net>, Marc Kleine-Budde <mkl@pengutronix.de>
+Message-ID: <20260807074757.104211-2-socketcan@hartkopp.net>
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+commit 050f010f920da17c1044a4f174766ad553e770b6 upstream.
+
+This patch is a follow-up to commit cf070fe33bfb ("can: isotp: serialize
+TX state transitions under so->rx_lock") which addresses following
+sashiko-bot findings:
+
+- isotp_sendmsg(): drain so->txfrtimer first so a stale callback can't
+  re-arm echotimer after the claim
+
+- isotp_release(): wake so->wait after forcing ISOTP_SHUTDOWN so a
+  sleeping sendmsg() claim isn't stranded
+
+- isotp_sendmsg(): have both wait_event_interruptible() calls in
+  isotp_sendmsg() also wake on ISOTP_SHUTDOWN and do not return claim to
+  IDLE to avoid corrupting a concurrent isotp_release() process.
+
+- isotp_sendmsg(): handle potential claim of a new transfer when
+  the wait_event_interruptible() call returns in CAN_ISOTP_WAIT_TX_DONE
+  mode. Don't touch timers and states of the new transfer if a new thread
+  incremented so->tx_gen before getting the lock at err_event_drop.
+
+- isotp_sendmsg(): handle a stuck can_send() and omit timer and state
+  changes if a new transfer was claimed. wait_tx_done() returns the error
+  recorded in so->tx_result[], tagged with the caller's own generation.
+
+- isotp_tx_timeout(): on a claimed timeout, record the ECOMM error for
+  the timed-out transfer's own generation in so->tx_result[]; sk->sk_err
+  is raised unconditionally, same as every other error path here.
+
+- isotp_tx_gen_done()/isotp_tx_timeout(): always read tx.state (acquire)
+  before tx_gen - the reverse order let a weakly ordered CPU pair a fresh
+  tx.state with a stale tx_gen/tx_result slot.
+
+- isotp_sendmsg(): wait_tx_done: drain sk_err via sock_error() once we
+  have read the result from so->tx_result[], so an already-reported error
+  doesn't stay latched for a later poll()/SO_ERROR.
+
+Also align the remaining lock-free so->tx.state/rx.state/cfecho accesses
+and use skb->hash as unique loopback echo frame indicator.
+
+Fixes: cf070fe33bfb ("can: isotp: serialize TX state transitions under so->rx_lock")
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Link: https://patch.msgid.link/20260724181525.43556-1-socketcan@hartkopp.net
+Cc: stable@kernel.org
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/can/isotp.c |  317 ++++++++++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 230 insertions(+), 87 deletions(-)
+
+--- a/net/can/isotp.c
++++ b/net/can/isotp.c
+@@ -125,6 +125,15 @@ MODULE_PARM_DESC(max_pdu_size, "maximum
+ #define ISOTP_FC_TIMEOUT 1    /* 1 sec */
+ #define ISOTP_ECHO_TIMEOUT 2  /* 2 secs */
++/* so->tx_result[so->tx_gen % ISOTP_TX_RESULT_SLOTS] holds the packed value
++ * (err << ISOTP_TX_RESULT_GEN_BITS | gen) for each tx generation slot, so it
++ * can be handled with a single READ_ONCE()/WRITE_ONCE() access.
++ */
++#define ISOTP_TX_RESULT_SLOTS 4
++#define ISOTP_TX_RESULT_GEN_BITS 24
++#define ISOTP_TX_RESULT_GEN_MASK ((1U << ISOTP_TX_RESULT_GEN_BITS) - 1)
++#define ISOTP_TX_RESULT_ERR_MASK 0xFF
++
+ enum {
+       ISOTP_IDLE = 0,
+       ISOTP_WAIT_FIRST_FC,
+@@ -163,7 +172,8 @@ struct isotp_sock {
+       u32 force_tx_stmin;
+       u32 force_rx_stmin;
+       u32 cfecho; /* consecutive frame echo tag */
+-      u32 tx_gen; /* generation, bumped per new tx transfer */
++      u32 tx_gen; /* transfer generation, increased per new tx transfer */
++      u32 tx_result[ISOTP_TX_RESULT_SLOTS]; /* per-generation result slots */
+       struct tpcon rx, tx;
+       struct list_head notifier;
+       wait_queue_head_t wait;
+@@ -174,6 +184,65 @@ static LIST_HEAD(isotp_notifier_list);
+ static DEFINE_SPINLOCK(isotp_notifier_lock);
+ static struct isotp_sock *isotp_busy_notifier;
++/* increase (24 bit) tx generation value */
++static u32 isotp_inc_tx_gen(u32 gen)
++{
++      return (gen + 1) & ISOTP_TX_RESULT_GEN_MASK;
++}
++
++/* store 8 bit error and 24 bit tx generation values in packed u32 element */
++static u32 isotp_pack_tx_result(u32 gen, int err)
++{
++      return gen | ((u32)err << ISOTP_TX_RESULT_GEN_BITS);
++}
++
++/* get the 24 bit tx generation value from the tx result */
++static u32 isotp_get_tx_gen(u32 gen_err)
++{
++      return gen_err & ISOTP_TX_RESULT_GEN_MASK;
++}
++
++/* get the 8 bit error value from the tx result */
++static u32 isotp_get_tx_err(u32 gen_err)
++{
++      return (gen_err >> ISOTP_TX_RESULT_GEN_BITS) & ISOTP_TX_RESULT_ERR_MASK;
++}
++
++/* store transfer result in per-generation%4 so->tx_result[] slot */
++static void isotp_set_tx_result(struct isotp_sock *so, u32 gen, int err)
++{
++      WRITE_ONCE(so->tx_result[gen % ISOTP_TX_RESULT_SLOTS],
++                 isotp_pack_tx_result(gen, err));
++}
++
++/* fetch the result recorded for 'gen', as a (negative) errno (0 for success) */
++static int isotp_get_tx_result(struct isotp_sock *so, u32 gen)
++{
++      u32 result = READ_ONCE(so->tx_result[gen % ISOTP_TX_RESULT_SLOTS]);
++
++      if (isotp_get_tx_gen(result) != gen) {
++              pr_notice_once("can-isotp: tx_result[] slot reused before read\n");
++
++              /* report failure rather than risk a false success */
++              return -ECOMM;
++      }
++
++      return -(isotp_get_tx_err(result));
++}
++
++/* true if done, shut down or superseded ('gen' is no longer the active
++ * transfer). Reads tx.state first (acquire) so tx_gen/tx_result reads
++ * below see at least what that state write published (common sequence).
++ */
++static bool isotp_tx_gen_done(struct isotp_sock *so, u32 gen)
++{
++      /* read tx.state first for the common sequence */
++      u32 state = smp_load_acquire(&so->tx.state);
++
++      return state == ISOTP_IDLE || state == ISOTP_SHUTDOWN ||
++             READ_ONCE(so->tx_gen) != gen;
++}
++
+ static inline struct isotp_sock *isotp_sk(const struct sock *sk)
+ {
+       return (struct isotp_sock *)sk;
+@@ -196,7 +265,7 @@ static enum hrtimer_restart isotp_rx_tim
+                                            rxtimer);
+       struct sock *sk = &so->sk;
+-      if (so->rx.state == ISOTP_WAIT_DATA) {
++      if (READ_ONCE(so->rx.state) == ISOTP_WAIT_DATA) {
+               /* we did not get new data frames in time */
+               /* report 'connection timed out' */
+@@ -205,7 +274,7 @@ static enum hrtimer_restart isotp_rx_tim
+                       sk_error_report(sk);
+               /* reset rx state */
+-              so->rx.state = ISOTP_IDLE;
++              WRITE_ONCE(so->rx.state, ISOTP_IDLE);
+       }
+       return HRTIMER_NORESTART;
+@@ -362,20 +431,19 @@ static void isotp_send_cframe(struct iso
+ static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
+ {
+       struct sock *sk = &so->sk;
++      int tx_err = EBADMSG; /* default for unknown FC status */
+-      if (so->tx.state != ISOTP_WAIT_FC &&
+-          so->tx.state != ISOTP_WAIT_FIRST_FC)
++      if (READ_ONCE(so->tx.state) != ISOTP_WAIT_FC &&
++          READ_ONCE(so->tx.state) != ISOTP_WAIT_FIRST_FC)
+               return 0;
+       hrtimer_cancel(&so->txtimer);
+       /* isotp_tx_timeout() may have given up on this job while
+-       * hrtimer_cancel() above waited for it to finish; so->rx_lock
+-       * (held by our caller isotp_rcv()) rules out a concurrent claim,
+-       * so a plain recheck is enough here.
++       * hrtimer_cancel() above waited for it to finish => recheck
+        */
+-      if (so->tx.state != ISOTP_WAIT_FC &&
+-          so->tx.state != ISOTP_WAIT_FIRST_FC)
++      if (READ_ONCE(so->tx.state) != ISOTP_WAIT_FC &&
++          READ_ONCE(so->tx.state) != ISOTP_WAIT_FIRST_FC)
+               return 1;
+       if ((cf->len < ae + FC_CONTENT_SZ) ||
+@@ -386,13 +454,15 @@ static int isotp_rcv_fc(struct isotp_soc
+               if (!sock_flag(sk, SOCK_DEAD))
+                       sk_error_report(sk);
+-              so->tx.state = ISOTP_IDLE;
++              isotp_set_tx_result(so, so->tx_gen, EBADMSG);
++              /* set to IDLE after publishing tx_result */
++              smp_store_release(&so->tx.state, ISOTP_IDLE);
+               wake_up_interruptible(&so->wait);
+               return 1;
+       }
+       /* get communication parameters only from the first FC frame */
+-      if (so->tx.state == ISOTP_WAIT_FIRST_FC) {
++      if (READ_ONCE(so->tx.state) == ISOTP_WAIT_FIRST_FC) {
+               so->txfc.bs = cf->data[ae + 1];
+               so->txfc.stmin = cf->data[ae + 2];
+@@ -415,13 +485,13 @@ static int isotp_rcv_fc(struct isotp_soc
+                       so->tx_gap = ktime_add_ns(so->tx_gap,
+                                                 (so->txfc.stmin - 0xF0)
+                                                 * 100000);
+-              so->tx.state = ISOTP_WAIT_FC;
++              WRITE_ONCE(so->tx.state, ISOTP_WAIT_FC);
+       }
+       switch (cf->data[ae] & 0x0F) {
+       case ISOTP_FC_CTS:
+               so->tx.bs = 0;
+-              so->tx.state = ISOTP_SENDING;
++              WRITE_ONCE(so->tx.state, ISOTP_SENDING);
+               /* send CF frame and enable echo timeout handling */
+               hrtimer_start(&so->echotimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
+                             HRTIMER_MODE_REL_SOFT);
+@@ -436,14 +506,19 @@ static int isotp_rcv_fc(struct isotp_soc
+       case ISOTP_FC_OVFLW:
+               /* overflow on receiver side - report 'message too long' */
+-              sk->sk_err = EMSGSIZE;
+-              if (!sock_flag(sk, SOCK_DEAD))
+-                      sk_error_report(sk);
++              tx_err = EMSGSIZE;
+               fallthrough;
+       default:
+-              /* stop this tx job */
+-              so->tx.state = ISOTP_IDLE;
++              /* reserved/unknown flow status (tx_err defaults to EBADMSG) */
++
++              sk->sk_err = tx_err;
++              if (!sock_flag(sk, SOCK_DEAD))
++                      sk_error_report(sk);
++
++              isotp_set_tx_result(so, so->tx_gen, tx_err);
++              /* set to IDLE after publishing tx_result */
++              smp_store_release(&so->tx.state, ISOTP_IDLE);
+               wake_up_interruptible(&so->wait);
+       }
+       return 0;
+@@ -456,7 +531,7 @@ static int isotp_rcv_sf(struct sock *sk,
+       struct sk_buff *nskb;
+       hrtimer_cancel(&so->rxtimer);
+-      so->rx.state = ISOTP_IDLE;
++      WRITE_ONCE(so->rx.state, ISOTP_IDLE);
+       if (!len || len > cf->len - pcilen)
+               return 1;
+@@ -490,7 +565,7 @@ static int isotp_rcv_ff(struct sock *sk,
+       int ff_pci_sz;
+       hrtimer_cancel(&so->rxtimer);
+-      so->rx.state = ISOTP_IDLE;
++      WRITE_ONCE(so->rx.state, ISOTP_IDLE);
+       /* get the used sender LL_DL from the (first) CAN frame data length */
+       so->rx.ll_dl = padlen(cf->len);
+@@ -544,7 +619,7 @@ static int isotp_rcv_ff(struct sock *sk,
+       /* initial setup for this pdu reception */
+       so->rx.sn = 1;
+-      so->rx.state = ISOTP_WAIT_DATA;
++      WRITE_ONCE(so->rx.state, ISOTP_WAIT_DATA);
+       /* no creation of flow control frames */
+       if (so->opt.flags & CAN_ISOTP_LISTEN_MODE)
+@@ -562,7 +637,7 @@ static int isotp_rcv_cf(struct sock *sk,
+       struct sk_buff *nskb;
+       int i;
+-      if (so->rx.state != ISOTP_WAIT_DATA)
++      if (READ_ONCE(so->rx.state) != ISOTP_WAIT_DATA)
+               return 0;
+       /* drop if timestamp gap is less than force_rx_stmin nano secs */
+@@ -577,11 +652,9 @@ static int isotp_rcv_cf(struct sock *sk,
+       hrtimer_cancel(&so->rxtimer);
+       /* isotp_rx_timer_handler() may have raced us for so->rx.state
+-       * while hrtimer_cancel() above waited for it to finish, already
+-       * reporting ETIMEDOUT and resetting the reception; don't process
+-       * this CF into a reassembly that has already been given up on.
++       * while hrtimer_cancel() above waited for it to finish => recheck
+        */
+-      if (so->rx.state != ISOTP_WAIT_DATA)
++      if (READ_ONCE(so->rx.state) != ISOTP_WAIT_DATA)
+               return 1;
+       /* CFs are never longer than the FF */
+@@ -602,7 +675,7 @@ static int isotp_rcv_cf(struct sock *sk,
+                       sk_error_report(sk);
+               /* reset rx state */
+-              so->rx.state = ISOTP_IDLE;
++              WRITE_ONCE(so->rx.state, ISOTP_IDLE);
+               return 1;
+       }
+       so->rx.sn++;
+@@ -616,7 +689,7 @@ static int isotp_rcv_cf(struct sock *sk,
+       if (so->rx.idx >= so->rx.len) {
+               /* we are done */
+-              so->rx.state = ISOTP_IDLE;
++              WRITE_ONCE(so->rx.state, ISOTP_IDLE);
+               if ((so->opt.flags & ISOTP_CHECK_PADDING) &&
+                   check_pad(so, cf, i + 1, so->opt.rxpad_content)) {
+@@ -687,8 +760,10 @@ static void isotp_rcv(struct sk_buff *sk
+       if (so->opt.flags & CAN_ISOTP_HALF_DUPLEX) {
+               /* check rx/tx path half duplex expectations */
+-              if ((so->tx.state != ISOTP_IDLE && n_pci_type != N_PCI_FC) ||
+-                  (so->rx.state != ISOTP_IDLE && n_pci_type == N_PCI_FC))
++              if ((READ_ONCE(so->tx.state) != ISOTP_IDLE &&
++                   n_pci_type != N_PCI_FC) ||
++                  (READ_ONCE(so->rx.state) != ISOTP_IDLE &&
++                   n_pci_type == N_PCI_FC))
+                       goto out_unlock;
+       }
+@@ -782,6 +857,7 @@ static void isotp_send_cframe(struct iso
+       struct canfd_frame *cf;
+       int can_send_ret;
+       int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0;
++      u32 old_cfecho;
+       dev = dev_get_by_index(sock_net(sk), so->ifindex);
+       if (!dev)
+@@ -796,6 +872,9 @@ static void isotp_send_cframe(struct iso
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = dev->ifindex;
++      /* set uid in tx skb to identify CF echo frames */
++      can_set_skb_uid(skb);
++
+       cf = (struct canfd_frame *)skb->data;
+       skb_put_zero(skb, so->ll.mtu);
+@@ -812,12 +891,15 @@ static void isotp_send_cframe(struct iso
+       skb->dev = dev;
+       can_skb_set_owner(skb, sk);
+-      /* cfecho should have been zero'ed by init/isotp_rcv_echo() */
+-      if (so->cfecho)
+-              pr_notice_once("can-isotp: cfecho is %08X != 0\n", so->cfecho);
++      /* zero'ed by init/isotp_rcv_echo(); reached lock-free via
++       * isotp_txfr_timer_handler() too, so use READ_ONCE()/WRITE_ONCE()
++       */
++      old_cfecho = READ_ONCE(so->cfecho);
++      if (old_cfecho)
++              pr_notice_once("can-isotp: cfecho is %08X != 0\n", old_cfecho);
+       /* set consecutive frame echo tag */
+-      so->cfecho = *(u32 *)cf->data;
++      WRITE_ONCE(so->cfecho, skb->hash);
+       /* send frame with local echo enabled */
+       can_send_ret = can_send(skb, 1);
+@@ -869,7 +951,6 @@ static void isotp_rcv_echo(struct sk_buf
+ {
+       struct sock *sk = (struct sock *)data;
+       struct isotp_sock *so = isotp_sk(sk);
+-      struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+       /* only handle my own local echo CF/SF skb's (no FF!) */
+       if (skb->sk != sk)
+@@ -881,32 +962,35 @@ static void isotp_rcv_echo(struct sk_buf
+       spin_lock(&so->rx_lock);
+       /* so->cfecho may since belong to a new transfer; recheck under lock */
+-      if (so->cfecho != *(u32 *)cf->data)
++      if (READ_ONCE(so->cfecho) != skb->hash)
+               goto out_unlock;
+       /* cancel local echo timeout */
+       hrtimer_cancel(&so->echotimer);
+       /* local echo skb with consecutive frame has been consumed */
+-      so->cfecho = 0;
++      WRITE_ONCE(so->cfecho, 0);
+       /* claiming a transfer also takes so->rx_lock, so a plain recheck
+        * is enough: so->tx.state can't have flipped to ISOTP_SENDING for
+        * a new claim while we're still in here
+        */
+-      if (so->tx.state != ISOTP_SENDING)
++      if (READ_ONCE(so->tx.state) != ISOTP_SENDING)
+               goto out_unlock;
+       if (so->tx.idx >= so->tx.len) {
+               /* we are done */
+-              so->tx.state = ISOTP_IDLE;
++
++              isotp_set_tx_result(so, so->tx_gen, 0);
++              /* set to IDLE after publishing tx_result */
++              smp_store_release(&so->tx.state, ISOTP_IDLE);
+               wake_up_interruptible(&so->wait);
+               goto out_unlock;
+       }
+       if (so->txfc.bs && so->tx.bs >= so->txfc.bs) {
+               /* stop and wait for FC with timeout */
+-              so->tx.state = ISOTP_WAIT_FC;
++              WRITE_ONCE(so->tx.state, ISOTP_WAIT_FC);
+               hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
+                             HRTIMER_MODE_REL_SOFT);
+               goto out_unlock;
+@@ -928,16 +1012,20 @@ out_unlock:
+       spin_unlock(&so->rx_lock);
+ }
+-/* shared by so->txtimer's and so->echotimer's callbacks. Both timers get
+- * cancelled under so->rx_lock elsewhere, so this must stay lock-free to
+- * avoid deadlocking with that; uses so->tx_gen instead to avoid tainting
+- * a new transfer with an error from the one that just timed out.
++/* isotp_tx_timeout: we did not get any flow control or echo frame in time
++ *
++ * Shared by so->txtimer's and so->echotimer's callbacks. Both timers get
++ * cancelled under so->rx_lock elsewhere, so this must stay lock-free.
++ *
++ * tx.state is acquired before tx_gen. Common sequence in isotp_tx_gen_done().
++ * cmpxchg() only orders itself, not the two preceding loads.
+  */
+ static enum hrtimer_restart isotp_tx_timeout(struct isotp_sock *so)
+ {
+       struct sock *sk = &so->sk;
++      /* read tx.state first for the common sequence */
++      u32 old_state = smp_load_acquire(&so->tx.state);
+       u32 gen = READ_ONCE(so->tx_gen);
+-      u32 old_state = READ_ONCE(so->tx.state);
+       /* don't handle timeouts in IDLE or SHUTDOWN state */
+       if (old_state == ISOTP_IDLE || old_state == ISOTP_SHUTDOWN)
+@@ -947,14 +1035,14 @@ static enum hrtimer_restart isotp_tx_tim
+       if (cmpxchg(&so->tx.state, old_state, ISOTP_IDLE) != old_state)
+               return HRTIMER_NORESTART;
+-      /* we did not get any flow control or echo frame in time */
++      /* detected timeout: report 'communication error on send' */
+-      if (READ_ONCE(so->tx_gen) == gen) {
+-              /* report 'communication error on send' */
+-              sk->sk_err = ECOMM;
+-              if (!sock_flag(sk, SOCK_DEAD))
+-                      sk_error_report(sk);
+-      }
++      /* a stale read of this slot by a waiter still falls back to ECOMM */
++      isotp_set_tx_result(so, gen, ECOMM);
++
++      sk->sk_err = ECOMM;
++      if (!sock_flag(sk, SOCK_DEAD))
++              sk_error_report(sk);
+       wake_up_interruptible(&so->wait);
+@@ -989,7 +1077,7 @@ static enum hrtimer_restart isotp_txfr_t
+                     HRTIMER_MODE_REL_SOFT);
+       /* cfecho should be consumed by isotp_rcv_echo() here */
+-      if (so->tx.state == ISOTP_SENDING && !so->cfecho)
++      if (READ_ONCE(so->tx.state) == ISOTP_SENDING && !READ_ONCE(so->cfecho))
+               isotp_send_cframe(so);
+       return HRTIMER_NORESTART;
+@@ -1007,10 +1095,12 @@ static int isotp_sendmsg(struct socket *
+       s64 hrtimer_sec = ISOTP_ECHO_TIMEOUT;
+       struct hrtimer *tx_hrt = &so->echotimer;
+       u32 new_state = ISOTP_SENDING;
++      u32 my_gen;
++      u32 old_cfecho;
+       int off;
+       int err;
+-      if (!so->bound || so->tx.state == ISOTP_SHUTDOWN)
++      if (!so->bound || READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN)
+               return -EADDRNOTAVAIL;
+       /* claim the socket under so->rx_lock: this serializes the claim
+@@ -1027,29 +1117,33 @@ static int isotp_sendmsg(struct socket *
+               if (msg->msg_flags & MSG_DONTWAIT)
+                       return -EAGAIN;
+-              if (so->tx.state == ISOTP_SHUTDOWN)
++              if (READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN)
+                       return -EADDRNOTAVAIL;
+               /* wait for complete transmission of current pdu */
+               err = wait_event_interruptible(so->wait,
+-                                             so->tx.state == ISOTP_IDLE);
++                                             READ_ONCE(so->tx.state) == ISOTP_IDLE ||
++                                             READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN);
+               if (err)
+                       return err;
+       }
+-      /* new transfer: bump so->tx_gen and drain the old one's timers,
+-       * still under the so->rx_lock we just claimed the socket with
+-       */
+-      WRITE_ONCE(so->tx.state, ISOTP_SENDING);
+-      WRITE_ONCE(so->tx_gen, READ_ONCE(so->tx_gen) + 1);
++      /* txfrtimer's callback re-arms echotimer lock-free: drain it first */
++      hrtimer_cancel(&so->txfrtimer);
+       hrtimer_cancel(&so->txtimer);
+       hrtimer_cancel(&so->echotimer);
+-      hrtimer_cancel(&so->txfrtimer);
+-      so->cfecho = 0;
++
++      /* new transfer: increment so->tx_gen and set tx.state after barrier */
++      my_gen = isotp_inc_tx_gen(READ_ONCE(so->tx_gen));
++      isotp_set_tx_result(so, my_gen, ECOMM); /* prevent stale slot matching */
++      WRITE_ONCE(so->tx_gen, my_gen);
++      smp_wmb(); /* see smp_load_acquire() in isotp_tx_[timeout|gen_done] */
++      WRITE_ONCE(so->tx.state, ISOTP_SENDING);
++      WRITE_ONCE(so->cfecho, 0);
+       spin_unlock_bh(&so->rx_lock);
+       /* so->bound is only checked once above - a wakeup may have
+-       * unbound/rebound the socket meanwhile, so re-validate it
++       * unbound/rebound the socket meanwhile => recheck
+        */
+       if (!so->bound) {
+               err = -EADDRNOTAVAIL;
+@@ -1101,6 +1195,9 @@ static int isotp_sendmsg(struct socket *
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = dev->ifindex;
++      /* set uid in tx skb to identify CF echo frames */
++      can_set_skb_uid(skb);
++
+       so->tx.len = size;
+       so->tx.idx = 0;
+@@ -1108,8 +1205,9 @@ static int isotp_sendmsg(struct socket *
+       skb_put_zero(skb, so->ll.mtu);
+       /* cfecho should have been zero'ed by init / former isotp_rcv_echo() */
+-      if (so->cfecho)
+-              pr_notice_once("can-isotp: uninit cfecho %08X\n", so->cfecho);
++      old_cfecho = READ_ONCE(so->cfecho);
++      if (old_cfecho)
++              pr_notice_once("can-isotp: uninit cfecho %08X\n", old_cfecho);
+       /* check for single frame transmission depending on TX_DL */
+       if (size <= so->tx.ll_dl - SF_PCI_SZ4 - ae - off) {
+@@ -1137,7 +1235,7 @@ static int isotp_sendmsg(struct socket *
+                       cf->data[ae] |= size;
+               /* set CF echo tag for isotp_rcv_echo() (SF-mode) */
+-              so->cfecho = *(u32 *)cf->data;
++              WRITE_ONCE(so->cfecho, skb->hash);
+       } else {
+               /* send first frame */
+@@ -1154,7 +1252,7 @@ static int isotp_sendmsg(struct socket *
+                       so->txfc.bs = 0;
+                       /* set CF echo tag for isotp_rcv_echo() (CF-mode) */
+-                      so->cfecho = *(u32 *)cf->data;
++                      WRITE_ONCE(so->cfecho, skb->hash);
+               } else {
+                       /* standard flow control check */
+                       new_state = ISOTP_WAIT_FIRST_FC;
+@@ -1164,12 +1262,12 @@ static int isotp_sendmsg(struct socket *
+                       tx_hrt = &so->txtimer;
+                       /* no CF echo tag for isotp_rcv_echo() (FF-mode) */
+-                      so->cfecho = 0;
++                      WRITE_ONCE(so->cfecho, 0);
+               }
+       }
+       spin_lock_bh(&so->rx_lock);
+-      if (so->tx.state == ISOTP_SHUTDOWN) {
++      if (READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN) {
+               /* isotp_release() has since taken over and already drained
+                * our timers - don't send into a socket that's going away
+                */
+@@ -1180,7 +1278,7 @@ static int isotp_sendmsg(struct socket *
+               return -EADDRNOTAVAIL;
+       }
+       /* WAIT_FIRST_FC for standard FF, else stays ISOTP_SENDING */
+-      so->tx.state = new_state;
++      WRITE_ONCE(so->tx.state, new_state);
+       hrtimer_start(tx_hrt, ktime_set(hrtimer_sec, 0),
+                     HRTIMER_MODE_REL_SOFT);
+       spin_unlock_bh(&so->rx_lock);
+@@ -1197,20 +1295,49 @@ static int isotp_sendmsg(struct socket *
+                              __func__, ERR_PTR(err));
+               spin_lock_bh(&so->rx_lock);
++
++              /* new transfer already claimed by a concurrent completion,
++               * timeout or sendmsg() while we were stuck in can_send()?
++               */
++              if (READ_ONCE(so->tx_gen) != my_gen) {
++                      /* don't touch timers and state of the new transfer */
++                      spin_unlock_bh(&so->rx_lock);
++                      return err;
++              }
++
+               /* no transmission -> no timeout monitoring */
+               hrtimer_cancel(tx_hrt);
+               goto err_out_drop_locked;
+       }
+       if (wait_tx_done) {
+-              /* wait for complete transmission of current pdu */
+-              err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
++              /* wake up for:
++               * - concurrent sendmsg() claiming a new transfer
++               * - complete transmission of current PDU
++               * - shutdown state change in isotp_release()
++               * isotp_tx_gen_done() uses common tx.state/tx_gen read sequence
++               */
++              err = wait_event_interruptible(so->wait,
++                                             isotp_tx_gen_done(so, my_gen));
+               if (err)
+                       goto err_event_drop;
+-              err = sock_error(sk);
+-              if (err)
+-                      return err;
++              /* still our claim, but isotp_release() force-shut it down */
++              if (smp_load_acquire(&so->tx.state) == ISOTP_SHUTDOWN &&
++                  READ_ONCE(so->tx_gen) == my_gen) {
++                      err = -EADDRNOTAVAIL;
++                      goto err_event_drop;
++              }
++
++              /* own completion, or tx_gen moved on - either way this is
++               * what isotp_get_tx_result() recorded for my_gen
++               */
++              err = isotp_get_tx_result(so, my_gen);
++
++              /* drain to avoid stale error for a later poll()/SO_ERROR */
++              sock_error(sk);
++
++              return err ? err : size;
+       }
+       return size;
+@@ -1220,15 +1347,26 @@ err_out_drop:
+       spin_lock_bh(&so->rx_lock);
+       goto err_out_drop_locked;
+ err_event_drop:
+-      /* interrupted waiting on our own transfer - drain its timers */
++      /* interrupted or shut down while waiting on our own transfer */
+       spin_lock_bh(&so->rx_lock);
++
++      /* new transfer already started by concurrent sendmsg()? */
++      if (READ_ONCE(so->tx_gen) != my_gen) {
++              /* don't touch timers and states of the new transfer */
++              spin_unlock_bh(&so->rx_lock);
++              return err;
++      }
++
+       hrtimer_cancel(&so->txfrtimer);
+       hrtimer_cancel(&so->txtimer);
+       hrtimer_cancel(&so->echotimer);
+ err_out_drop_locked:
+       /* release the claim; so->rx_lock still held from above */
+-      so->cfecho = 0;
+-      so->tx.state = ISOTP_IDLE;
++      WRITE_ONCE(so->cfecho, 0);
++
++      /* only claim to IDLE if isotp_release() has not taken over */
++      if (READ_ONCE(so->tx.state) != ISOTP_SHUTDOWN)
++              WRITE_ONCE(so->tx.state, ISOTP_IDLE);
+       spin_unlock_bh(&so->rx_lock);
+       wake_up_interruptible(&so->wait);
+@@ -1294,8 +1432,9 @@ static int isotp_release(struct socket *
+       /* best-effort: wait for a running pdu to finish, but don't block on
+        * it forever - give up after the first signal
+        */
+-      while (so->tx.state != ISOTP_IDLE &&
+-             wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0)
++      while (READ_ONCE(so->tx.state) != ISOTP_IDLE &&
++             wait_event_interruptible(so->wait,
++                                      READ_ONCE(so->tx.state) == ISOTP_IDLE) == 0)
+               ;
+       /* claim the socket under so->rx_lock like sendmsg() does, so its
+@@ -1303,9 +1442,12 @@ static int isotp_release(struct socket *
+        * unconditionally, even when a signal cut the wait above short
+        */
+       spin_lock_bh(&so->rx_lock);
+-      so->tx.state = ISOTP_SHUTDOWN;
++      WRITE_ONCE(so->tx.state, ISOTP_SHUTDOWN);
+       spin_unlock_bh(&so->rx_lock);
+-      so->rx.state = ISOTP_IDLE;
++      WRITE_ONCE(so->rx.state, ISOTP_IDLE);
++
++      /* forced SHUTDOWN may have skipped IDLE (gave up on a signal) */
++      wake_up_interruptible(&so->wait);
+       spin_lock(&isotp_notifier_lock);
+       while (isotp_busy_notifier == so) {
+@@ -1420,7 +1562,8 @@ static int isotp_bind(struct socket *soc
+        * with so->bound in the same lock_sock() section above, so there is
+        * no window in which a concurrent isotp_notify() could be missed.
+        */
+-      if (so->tx.state != ISOTP_IDLE || so->rx.state != ISOTP_IDLE) {
++      if (READ_ONCE(so->tx.state) != ISOTP_IDLE ||
++          READ_ONCE(so->rx.state) != ISOTP_IDLE) {
+               err = -EAGAIN;
+               goto out;
+       }
+@@ -1454,7 +1597,7 @@ static int isotp_bind(struct socket *soc
+                               isotp_rcv, sk, "isotp", sk);
+       /* no consecutive frame echo skb in flight */
+-      so->cfecho = 0;
++      WRITE_ONCE(so->cfecho, 0);
+       /* register for echo skb's */
+       can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id),
+@@ -1820,7 +1963,7 @@ static __poll_t isotp_poll(struct file *
+       poll_wait(file, &so->wait, wait);
+       /* Check for false positives due to TX state */
+-      if ((mask & EPOLLWRNORM) && (so->tx.state != ISOTP_IDLE))
++      if ((mask & EPOLLWRNORM) && (READ_ONCE(so->tx.state) != ISOTP_IDLE))
+               mask &= ~(EPOLLOUT | EPOLLWRNORM);
+       return mask;
diff --git a/queue-6.6/can-use-skb-hash-instead-of-private-variable-in-headroom.patch b/queue-6.6/can-use-skb-hash-instead-of-private-variable-in-headroom.patch
new file mode 100644 (file)
index 0000000..02ce5e5
--- /dev/null
@@ -0,0 +1,221 @@
+From stable+bounces-297171-greg=kroah.com@vger.kernel.org Fri Aug  7 09:51:47 2026
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+Date: Fri,  7 Aug 2026 09:47:56 +0200
+Subject: can: use skb hash instead of private variable in headroom
+To: stable@vger.kernel.org
+Cc: Oliver Hartkopp <socketcan@hartkopp.net>, Marc Kleine-Budde <mkl@pengutronix.de>
+Message-ID: <20260807074757.104211-1-socketcan@hartkopp.net>
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+commit d4fb6514ff8ed6912a71294e6b66a5d59ee88007 upstream.
+
+The can_skb_priv::skbcnt variable is used to identify CAN skbs in the RX
+path analogue to the skb->hash.
+
+As the skb hash is not filled in CAN skbs move the private skbcnt value to
+skb->hash and set skb->sw_hash accordingly. The skb->hash is a value used
+for RPS to identify skbs. Use it as intended.
+
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Link: https://patch.msgid.link/20260201-can_skb_ext-v8-1-3635d790fe8b@hartkopp.net
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/dev/skb.c |    2 --
+ include/linux/can/core.h  |    1 +
+ include/linux/can/skb.h   |    2 --
+ net/can/af_can.c          |   14 +++++++++++---
+ net/can/bcm.c             |    2 --
+ net/can/isotp.c           |    3 ---
+ net/can/j1939/socket.c    |    1 -
+ net/can/j1939/transport.c |    2 --
+ net/can/raw.c             |    7 +++----
+ 9 files changed, 15 insertions(+), 19 deletions(-)
+
+--- a/drivers/net/can/dev/skb.c
++++ b/drivers/net/can/dev/skb.c
+@@ -202,7 +202,6 @@ static void init_can_skb_reserve(struct
+       skb_reset_transport_header(skb);
+       can_skb_reserve(skb);
+-      can_skb_prv(skb)->skbcnt = 0;
+ }
+ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
+@@ -312,7 +311,6 @@ static bool can_skb_headroom_valid(struc
+       if (skb->ip_summed == CHECKSUM_NONE) {
+               /* init headroom */
+               can_skb_prv(skb)->ifindex = dev->ifindex;
+-              can_skb_prv(skb)->skbcnt = 0;
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+--- a/include/linux/can/core.h
++++ b/include/linux/can/core.h
+@@ -58,6 +58,7 @@ extern void can_rx_unregister(struct net
+                             void *data);
+ extern int can_send(struct sk_buff *skb, int loop);
++void can_set_skb_uid(struct sk_buff *skb);
+ void can_sock_destruct(struct sock *sk);
+ #endif /* !_CAN_CORE_H */
+--- a/include/linux/can/skb.h
++++ b/include/linux/can/skb.h
+@@ -49,13 +49,11 @@ bool can_dropped_invalid_skb(struct net_
+ /**
+  * struct can_skb_priv - private additional data inside CAN sk_buffs
+  * @ifindex:  ifindex of the first interface the CAN frame appeared on
+- * @skbcnt:   atomic counter to have an unique id together with skb pointer
+  * @frame_len:        length of CAN frame in data link layer
+  * @cf:               align to the following CAN frame at skb->data
+  */
+ struct can_skb_priv {
+       int ifindex;
+-      int skbcnt;
+       unsigned int frame_len;
+       struct can_frame cf[];
+ };
+--- a/net/can/af_can.c
++++ b/net/can/af_can.c
+@@ -639,6 +639,16 @@ static int can_rcv_filter(struct can_dev
+       return matches;
+ }
++void can_set_skb_uid(struct sk_buff *skb)
++{
++      /* create non-zero unique skb identifier together with *skb */
++      while (!(skb->hash))
++              skb->hash = atomic_inc_return(&skbcounter);
++
++      skb->sw_hash = 1;
++}
++EXPORT_SYMBOL(can_set_skb_uid);
++
+ static void can_receive(struct sk_buff *skb, struct net_device *dev)
+ {
+       struct can_dev_rcv_lists *dev_rcv_lists;
+@@ -650,9 +660,7 @@ static void can_receive(struct sk_buff *
+       atomic_long_inc(&pkg_stats->rx_frames);
+       atomic_long_inc(&pkg_stats->rx_frames_delta);
+-      /* create non-zero unique skb identifier together with *skb */
+-      while (!(can_skb_prv(skb)->skbcnt))
+-              can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter);
++      can_set_skb_uid(skb);
+       rcu_read_lock();
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -338,7 +338,6 @@ static void bcm_can_tx(struct bcm_op *op
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = dev->ifindex;
+-      can_skb_prv(skb)->skbcnt = 0;
+       skb_put_data(skb, cf, op->cfsiz);
+@@ -1582,7 +1581,6 @@ static int bcm_tx_send(struct msghdr *ms
+       }
+       can_skb_prv(skb)->ifindex = dev->ifindex;
+-      can_skb_prv(skb)->skbcnt = 0;
+       skb->dev = dev;
+       can_skb_set_owner(skb, sk);
+       err = can_send(skb, 1); /* send with loopback */
+--- a/net/can/isotp.c
++++ b/net/can/isotp.c
+@@ -231,7 +231,6 @@ static int isotp_send_fc(struct sock *sk
+       can_skb_reserve(nskb);
+       can_skb_prv(nskb)->ifindex = dev->ifindex;
+-      can_skb_prv(nskb)->skbcnt = 0;
+       nskb->dev = dev;
+       can_skb_set_owner(nskb, sk);
+@@ -796,7 +795,6 @@ static void isotp_send_cframe(struct iso
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = dev->ifindex;
+-      can_skb_prv(skb)->skbcnt = 0;
+       cf = (struct canfd_frame *)skb->data;
+       skb_put_zero(skb, so->ll.mtu);
+@@ -1102,7 +1100,6 @@ static int isotp_sendmsg(struct socket *
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = dev->ifindex;
+-      can_skb_prv(skb)->skbcnt = 0;
+       so->tx.len = size;
+       so->tx.idx = 0;
+--- a/net/can/j1939/socket.c
++++ b/net/can/j1939/socket.c
+@@ -889,7 +889,6 @@ static struct sk_buff *j1939_sk_alloc_sk
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = ndev->ifindex;
+-      can_skb_prv(skb)->skbcnt = 0;
+       skb_reserve(skb, offsetof(struct can_frame, data));
+       ret = memcpy_from_msg(skb_put(skb, size), msg, size);
+--- a/net/can/j1939/transport.c
++++ b/net/can/j1939/transport.c
+@@ -613,7 +613,6 @@ sk_buff *j1939_tp_tx_dat_new(struct j193
+       skb->dev = priv->ndev;
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = priv->ndev->ifindex;
+-      can_skb_prv(skb)->skbcnt = 0;
+       /* reserve CAN header */
+       skb_reserve(skb, offsetof(struct can_frame, data));
+@@ -1553,7 +1552,6 @@ j1939_session *j1939_session_fresh_new(s
+       skb->dev = priv->ndev;
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = priv->ndev->ifindex;
+-      can_skb_prv(skb)->skbcnt = 0;
+       skcb = j1939_skb_to_cb(skb);
+       memcpy(skcb, rel_skcb, sizeof(*skcb));
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -75,8 +75,8 @@ MODULE_ALIAS("can-proto-1");
+  */
+ struct uniqframe {
+-      int skbcnt;
+       const struct sk_buff *skb;
++      u32 hash;
+       unsigned int join_rx_count;
+ };
+@@ -140,7 +140,7 @@ static void raw_rcv(struct sk_buff *oskb
+       /* eliminate multiple filter matches for the same skb */
+       if (this_cpu_ptr(ro->uniq)->skb == oskb &&
+-          this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
++          this_cpu_ptr(ro->uniq)->hash == oskb->hash) {
+               if (!ro->join_filters)
+                       return;
+@@ -150,7 +150,7 @@ static void raw_rcv(struct sk_buff *oskb
+                       return;
+       } else {
+               this_cpu_ptr(ro->uniq)->skb = oskb;
+-              this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
++              this_cpu_ptr(ro->uniq)->hash = oskb->hash;
+               this_cpu_ptr(ro->uniq)->join_rx_count = 1;
+               /* drop first frame to check all enabled filters? */
+               if (ro->join_filters && ro->count > 1)
+@@ -871,7 +871,6 @@ static int raw_sendmsg(struct socket *so
+       can_skb_reserve(skb);
+       can_skb_prv(skb)->ifindex = dev->ifindex;
+-      can_skb_prv(skb)->skbcnt = 0;
+       /* fill the skb before testing for valid CAN frames */
+       err = memcpy_from_msg(skb_put(skb, size), msg, size);
diff --git a/queue-6.6/ceph-fix-refcount-leak-in-ceph_readdir.patch b/queue-6.6/ceph-fix-refcount-leak-in-ceph_readdir.patch
new file mode 100644 (file)
index 0000000..24de5b8
--- /dev/null
@@ -0,0 +1,55 @@
+From stable+bounces-297280-greg=kroah.com@vger.kernel.org Fri Aug  7 13:55:34 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  7 Aug 2026 07:48:08 -0400
+Subject: ceph: fix refcount leak in ceph_readdir()
+To: stable@vger.kernel.org
+Cc: WenTao Liang <vulab@iscas.ac.cn>, Viacheslav Dubeyko <slava@dubeyko.com>, Alex Markuze <amarkuze@redhat.com>, Ilya Dryomov <idryomov@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807114809.2056244-3-sashal@kernel.org>
+
+From: WenTao Liang <vulab@iscas.ac.cn>
+
+[ Upstream commit c3e64079d8b9663e3998d0caac9aba915b6b93ae ]
+
+The ceph_readdir() function allocates a ceph_mds_request via
+ceph_mdsc_create_request() and stores it in dfi->last_readdir. In
+the directory entry processing loop, if the entry's offset is less
+than ctx->pos or if the inode pointer is unexpectedly NULL, the
+function returns -EIO without releasing the reference held by
+dfi->last_readdir, causing a refcount leak.
+
+Fix this by adding ceph_mdsc_put_request(dfi->last_readdir) before
+returning on these error paths. Also set dfi->last_readdir to NULL
+for safety, matching the cleanup done at the normal exit.
+
+Cc: stable@vger.kernel.org
+Fixes: af9ffa6df7e3 ("ceph: add support to readdir for encrypted names")
+Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
+Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
+Reviewed-by: Alex Markuze <amarkuze@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/dir.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/fs/ceph/dir.c
++++ b/fs/ceph/dir.c
+@@ -546,11 +546,16 @@ more:
+                       pr_warn_client(cl,
+                               "%p %llx.%llx rde->offset 0x%llx ctx->pos 0x%llx\n",
+                               inode, ceph_vinop(inode), rde->offset, ctx->pos);
++                      ceph_mdsc_put_request(dfi->last_readdir);
++                      dfi->last_readdir = NULL;
+                       return -EIO;
+               }
+-              if (WARN_ON_ONCE(!rde->inode.in))
++              if (WARN_ON_ONCE(!rde->inode.in)) {
++                      ceph_mdsc_put_request(dfi->last_readdir);
++                      dfi->last_readdir = NULL;
+                       return -EIO;
++              }
+               ctx->pos = rde->offset;
+               doutc(cl, "%p %llx.%llx (%d/%d) -> %llx '%.*s' %p\n", inode,
diff --git a/queue-6.6/ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch b/queue-6.6/ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch
new file mode 100644 (file)
index 0000000..12595df
--- /dev/null
@@ -0,0 +1,9338 @@
+From stable+bounces-297288-greg=kroah.com@vger.kernel.org Fri Aug  7 13:52:14 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  7 Aug 2026 07:48:07 -0400
+Subject: ceph: print cluster fsid and client global_id in all debug logs
+To: stable@vger.kernel.org
+Cc: Xiubo Li <xiubli@redhat.com>, Patrick Donnelly <pdonnell@redhat.com>, Milind Changire <mchangir@redhat.com>, Ilya Dryomov <idryomov@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807114809.2056244-2-sashal@kernel.org>
+
+From: Xiubo Li <xiubli@redhat.com>
+
+[ Upstream commit 38d46409c4639a1d659ebfa70e27a8bed6b8ee1d ]
+
+Multiple CephFS mounts on a host is increasingly common so
+disambiguating messages like this is necessary and will make it easier
+to debug issues.
+
+At the same this will improve the debug logs to make them easier to
+troubleshooting issues, such as print the ino# instead only printing
+the memory addresses of the corresponding inodes and print the dentry
+names instead of the corresponding memory addresses for the dentry,etc.
+
+Link: https://tracker.ceph.com/issues/61590
+Signed-off-by: Xiubo Li <xiubli@redhat.com>
+Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
+Reviewed-by: Milind Changire <mchangir@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Stable-dep-of: c3e64079d8b9 ("ceph: fix refcount leak in ceph_readdir()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/acl.c        |    6 
+ fs/ceph/addr.c       |  279 +++++++++++---------
+ fs/ceph/caps.c       |  708 +++++++++++++++++++++++++++++----------------------
+ fs/ceph/crypto.c     |   39 +-
+ fs/ceph/debugfs.c    |    6 
+ fs/ceph/dir.c        |  218 +++++++++------
+ fs/ceph/export.c     |   39 +-
+ fs/ceph/file.c       |  245 ++++++++++-------
+ fs/ceph/inode.c      |  485 +++++++++++++++++++---------------
+ fs/ceph/ioctl.c      |   13 
+ fs/ceph/locks.c      |   57 ++--
+ fs/ceph/mds_client.c |  554 ++++++++++++++++++++++-----------------
+ fs/ceph/mdsmap.c     |   24 -
+ fs/ceph/metric.c     |    5 
+ fs/ceph/quota.c      |   29 +-
+ fs/ceph/snap.c       |  174 ++++++------
+ fs/ceph/super.c      |   70 ++---
+ fs/ceph/super.h      |    6 
+ fs/ceph/xattr.c      |   96 ++++--
+ 19 files changed, 1744 insertions(+), 1309 deletions(-)
+
+--- a/fs/ceph/acl.c
++++ b/fs/ceph/acl.c
+@@ -15,6 +15,7 @@
+ #include <linux/slab.h>
+ #include "super.h"
++#include "mds_client.h"
+ static inline void ceph_set_cached_acl(struct inode *inode,
+                                       int type, struct posix_acl *acl)
+@@ -31,6 +32,7 @@ static inline void ceph_set_cached_acl(s
+ struct posix_acl *ceph_get_acl(struct inode *inode, int type, bool rcu)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int size;
+       unsigned int retry_cnt = 0;
+       const char *name;
+@@ -72,8 +74,8 @@ retry:
+       } else if (size == -ENODATA || size == 0) {
+               acl = NULL;
+       } else {
+-              pr_err_ratelimited("get acl %llx.%llx failed, err=%d\n",
+-                                 ceph_vinop(inode), size);
++              pr_err_ratelimited_client(cl, "%llx.%llx failed, err=%d\n",
++                                        ceph_vinop(inode), size);
+               acl = ERR_PTR(-EIO);
+       }
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -79,18 +79,18 @@ static inline struct ceph_snap_context *
+  */
+ static bool ceph_dirty_folio(struct address_space *mapping, struct folio *folio)
+ {
+-      struct inode *inode;
++      struct inode *inode = mapping->host;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci;
+       struct ceph_snap_context *snapc;
+       if (folio_test_dirty(folio)) {
+-              dout("%p dirty_folio %p idx %lu -- already dirty\n",
+-                   mapping->host, folio, folio->index);
++              doutc(cl, "%llx.%llx %p idx %lu -- already dirty\n",
++                    ceph_vinop(inode), folio, folio->index);
+               VM_BUG_ON_FOLIO(!folio_test_private(folio), folio);
+               return false;
+       }
+-      inode = mapping->host;
+       ci = ceph_inode(inode);
+       /* dirty the head */
+@@ -110,12 +110,12 @@ static bool ceph_dirty_folio(struct addr
+       if (ci->i_wrbuffer_ref == 0)
+               ihold(inode);
+       ++ci->i_wrbuffer_ref;
+-      dout("%p dirty_folio %p idx %lu head %d/%d -> %d/%d "
+-           "snapc %p seq %lld (%d snaps)\n",
+-           mapping->host, folio, folio->index,
+-           ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref_head-1,
+-           ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head,
+-           snapc, snapc->seq, snapc->num_snaps);
++      doutc(cl, "%llx.%llx %p idx %lu head %d/%d -> %d/%d "
++            "snapc %p seq %lld (%d snaps)\n",
++            ceph_vinop(inode), folio, folio->index,
++            ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref_head-1,
++            ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head,
++            snapc, snapc->seq, snapc->num_snaps);
+       spin_unlock(&ci->i_ceph_lock);
+       /*
+@@ -136,23 +136,22 @@ static bool ceph_dirty_folio(struct addr
+ static void ceph_invalidate_folio(struct folio *folio, size_t offset,
+                               size_t length)
+ {
+-      struct inode *inode;
+-      struct ceph_inode_info *ci;
++      struct inode *inode = folio->mapping->host;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
++      struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_snap_context *snapc;
+-      inode = folio->mapping->host;
+-      ci = ceph_inode(inode);
+       if (offset != 0 || length != folio_size(folio)) {
+-              dout("%p invalidate_folio idx %lu partial dirty page %zu~%zu\n",
+-                   inode, folio->index, offset, length);
++              doutc(cl, "%llx.%llx idx %lu partial dirty page %zu~%zu\n",
++                    ceph_vinop(inode), folio->index, offset, length);
+               return;
+       }
+       WARN_ON(!folio_test_locked(folio));
+       if (folio_test_private(folio)) {
+-              dout("%p invalidate_folio idx %lu full dirty page\n",
+-                   inode, folio->index);
++              doutc(cl, "%llx.%llx idx %lu full dirty page\n",
++                    ceph_vinop(inode), folio->index);
+               snapc = folio_detach_private(folio);
+               ceph_put_wrbuffer_cap_refs(ci, 1, snapc);
+@@ -165,10 +164,10 @@ static void ceph_invalidate_folio(struct
+ static bool ceph_release_folio(struct folio *folio, gfp_t gfp)
+ {
+       struct inode *inode = folio->mapping->host;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+-      dout("%llx:%llx release_folio idx %lu (%sdirty)\n",
+-           ceph_vinop(inode),
+-           folio->index, folio_test_dirty(folio) ? "" : "not ");
++      doutc(cl, "%llx.%llx idx %lu (%sdirty)\n", ceph_vinop(inode),
++            folio->index, folio_test_dirty(folio) ? "" : "not ");
+       if (folio_test_private(folio))
+               return false;
+@@ -244,6 +243,7 @@ static void finish_netfs_read(struct cep
+ {
+       struct inode *inode = req->r_inode;
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_osd_data *osd_data = osd_req_op_extent_osd_data(req, 0);
+       struct netfs_io_subrequest *subreq = req->r_priv;
+       struct ceph_osd_req_op *op = &req->r_ops[0];
+@@ -253,8 +253,8 @@ static void finish_netfs_read(struct cep
+       ceph_update_read_metrics(&fsc->mdsc->metric, req->r_start_latency,
+                                req->r_end_latency, osd_data->length, err);
+-      dout("%s: result %d subreq->len=%zu i_size=%lld\n", __func__, req->r_result,
+-           subreq->len, i_size_read(req->r_inode));
++      doutc(cl, "result %d subreq->len=%zu i_size=%lld\n", req->r_result,
++            subreq->len, i_size_read(req->r_inode));
+       /* no object means success but no data */
+       if (err == -ENOENT)
+@@ -348,6 +348,7 @@ static void ceph_netfs_issue_read(struct
+       struct inode *inode = rreq->inode;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_osd_request *req = NULL;
+       struct ceph_vino vino = ceph_vino(inode);
+       struct iov_iter iter;
+@@ -384,7 +385,8 @@ static void ceph_netfs_issue_read(struct
+                       goto out;
+       }
+-      dout("%s: pos=%llu orig_len=%zu len=%llu\n", __func__, subreq->start, subreq->len, len);
++      doutc(cl, "%llx.%llx pos=%llu orig_len=%zu len=%llu\n",
++            ceph_vinop(inode), subreq->start, subreq->len, len);
+       iov_iter_xarray(&iter, ITER_DEST, &rreq->mapping->i_pages, subreq->start, len);
+@@ -401,8 +403,8 @@ static void ceph_netfs_issue_read(struct
+               err = iov_iter_get_pages_alloc2(&iter, &pages, len, &page_off);
+               if (err < 0) {
+-                      dout("%s: iov_ter_get_pages_alloc returned %d\n",
+-                           __func__, err);
++                      doutc(cl, "%llx.%llx failed to allocate pages, %d\n",
++                            ceph_vinop(inode), err);
+                       goto out;
+               }
+@@ -430,12 +432,13 @@ out:
+       ceph_osdc_put_request(req);
+       if (err)
+               netfs_subreq_terminated(subreq, err, false);
+-      dout("%s: result %d\n", __func__, err);
++      doutc(cl, "%llx.%llx result %d\n", ceph_vinop(inode), err);
+ }
+ static int ceph_init_request(struct netfs_io_request *rreq, struct file *file)
+ {
+       struct inode *inode = rreq->inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int got = 0, want = CEPH_CAP_FILE_CACHE;
+       struct ceph_netfs_request_data *priv;
+       int ret = 0;
+@@ -467,12 +470,12 @@ static int ceph_init_request(struct netf
+        */
+       ret = ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, true, &got);
+       if (ret < 0) {
+-              dout("start_read %p, error getting cap\n", inode);
++              doutc(cl, "%llx.%llx, error getting cap\n", ceph_vinop(inode));
+               goto out;
+       }
+       if (!(got & want)) {
+-              dout("start_read %p, no cache cap\n", inode);
++              doutc(cl, "%llx.%llx, no cache cap\n", ceph_vinop(inode));
+               ret = -EACCES;
+               goto out;
+       }
+@@ -567,13 +570,14 @@ get_oldest_context(struct inode *inode,
+                  struct ceph_snap_context *page_snapc)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_snap_context *snapc = NULL;
+       struct ceph_cap_snap *capsnap = NULL;
+       spin_lock(&ci->i_ceph_lock);
+       list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) {
+-              dout(" cap_snap %p snapc %p has %d dirty pages\n", capsnap,
+-                   capsnap->context, capsnap->dirty_pages);
++              doutc(cl, " capsnap %p snapc %p has %d dirty pages\n",
++                    capsnap, capsnap->context, capsnap->dirty_pages);
+               if (!capsnap->dirty_pages)
+                       continue;
+@@ -605,8 +609,8 @@ get_oldest_context(struct inode *inode,
+       }
+       if (!snapc && ci->i_wrbuffer_ref_head) {
+               snapc = ceph_get_snap_context(ci->i_head_snapc);
+-              dout(" head snapc %p has %d dirty pages\n",
+-                   snapc, ci->i_wrbuffer_ref_head);
++              doutc(cl, " head snapc %p has %d dirty pages\n", snapc,
++                    ci->i_wrbuffer_ref_head);
+               if (ctl) {
+                       ctl->i_size = i_size_read(inode);
+                       ctl->truncate_size = ci->i_truncate_size;
+@@ -663,6 +667,7 @@ static int writepage_nounlock(struct pag
+       struct inode *inode = page->mapping->host;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_snap_context *snapc, *oldest;
+       loff_t page_off = page_offset(page);
+       int err;
+@@ -674,7 +679,8 @@ static int writepage_nounlock(struct pag
+       bool caching = ceph_is_cache_enabled(inode);
+       struct page *bounce_page = NULL;
+-      dout("writepage %p idx %lu\n", page, page->index);
++      doutc(cl, "%llx.%llx page %p idx %lu\n", ceph_vinop(inode), page,
++            page->index);
+       if (ceph_inode_is_shutdown(inode))
+               return -EIO;
+@@ -682,13 +688,14 @@ static int writepage_nounlock(struct pag
+       /* verify this is a writeable snap context */
+       snapc = page_snap_context(page);
+       if (!snapc) {
+-              dout("writepage %p page %p not dirty?\n", inode, page);
++              doutc(cl, "%llx.%llx page %p not dirty?\n", ceph_vinop(inode),
++                    page);
+               return 0;
+       }
+       oldest = get_oldest_context(inode, &ceph_wbc, snapc);
+       if (snapc->seq > oldest->seq) {
+-              dout("writepage %p page %p snapc %p not writeable - noop\n",
+-                   inode, page, snapc);
++              doutc(cl, "%llx.%llx page %p snapc %p not writeable - noop\n",
++                    ceph_vinop(inode), page, snapc);
+               /* we should only noop if called by kswapd */
+               WARN_ON(!(current->flags & PF_MEMALLOC));
+               ceph_put_snap_context(oldest);
+@@ -699,8 +706,8 @@ static int writepage_nounlock(struct pag
+       /* is this a partial page at end of file? */
+       if (page_off >= ceph_wbc.i_size) {
+-              dout("folio at %lu beyond eof %llu\n", folio->index,
+-                              ceph_wbc.i_size);
++              doutc(cl, "%llx.%llx folio at %lu beyond eof %llu\n",
++                    ceph_vinop(inode), folio->index, ceph_wbc.i_size);
+               folio_invalidate(folio, 0, folio_size(folio));
+               return 0;
+       }
+@@ -709,8 +716,9 @@ static int writepage_nounlock(struct pag
+               len = ceph_wbc.i_size - page_off;
+       wlen = IS_ENCRYPTED(inode) ? round_up(len, CEPH_FSCRYPT_BLOCK_SIZE) : len;
+-      dout("writepage %p page %p index %lu on %llu~%llu snapc %p seq %lld\n",
+-           inode, page, page->index, page_off, wlen, snapc, snapc->seq);
++      doutc(cl, "%llx.%llx page %p index %lu on %llu~%llu snapc %p seq %lld\n",
++            ceph_vinop(inode), page, page->index, page_off, wlen, snapc,
++            snapc->seq);
+       if (atomic_long_inc_return(&fsc->writeback_count) >
+           CONGESTION_ON_THRESH(fsc->mount_options->congestion_kb))
+@@ -751,8 +759,9 @@ static int writepage_nounlock(struct pag
+       osd_req_op_extent_osd_data_pages(req, 0,
+                       bounce_page ? &bounce_page : &page, wlen, 0,
+                       false, false);
+-      dout("writepage %llu~%llu (%llu bytes, %sencrypted)\n",
+-           page_off, len, wlen, IS_ENCRYPTED(inode) ? "" : "not ");
++      doutc(cl, "%llx.%llx %llu~%llu (%llu bytes, %sencrypted)\n",
++            ceph_vinop(inode), page_off, len, wlen,
++            IS_ENCRYPTED(inode) ? "" : "not ");
+       req->r_mtime = inode->i_mtime;
+       ceph_osdc_start_request(osdc, req);
+@@ -771,19 +780,21 @@ static int writepage_nounlock(struct pag
+                       wbc = &tmp_wbc;
+               if (err == -ERESTARTSYS) {
+                       /* killed by SIGKILL */
+-                      dout("writepage interrupted page %p\n", page);
++                      doutc(cl, "%llx.%llx interrupted page %p\n",
++                            ceph_vinop(inode), page);
+                       redirty_page_for_writepage(wbc, page);
+                       end_page_writeback(page);
+                       return err;
+               }
+               if (err == -EBLOCKLISTED)
+                       fsc->blocklisted = true;
+-              dout("writepage setting page/mapping error %d %p\n",
+-                   err, page);
++              doutc(cl, "%llx.%llx setting page/mapping error %d %p\n",
++                    ceph_vinop(inode), err, page);
+               mapping_set_error(&inode->i_data, err);
+               wbc->pages_skipped++;
+       } else {
+-              dout("writepage cleaned page %p\n", page);
++              doutc(cl, "%llx.%llx cleaned page %p\n",
++                    ceph_vinop(inode), page);
+               err = 0;  /* vfs expects us to return 0 */
+       }
+       oldest = detach_page_private(page);
+@@ -835,6 +846,7 @@ static void writepages_finish(struct cep
+ {
+       struct inode *inode = req->r_inode;
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_osd_data *osd_data;
+       struct page *page;
+       int num_pages, total_pages = 0;
+@@ -846,7 +858,7 @@ static void writepages_finish(struct cep
+       unsigned int len = 0;
+       bool remove_page;
+-      dout("writepages_finish %p rc %d\n", inode, rc);
++      doutc(cl, "%llx.%llx rc %d\n", ceph_vinop(inode), rc);
+       if (rc < 0) {
+               mapping_set_error(mapping, rc);
+               ceph_set_error_write(ci);
+@@ -868,8 +880,10 @@ static void writepages_finish(struct cep
+       /* clean all pages */
+       for (i = 0; i < req->r_num_ops; i++) {
+               if (req->r_ops[i].op != CEPH_OSD_OP_WRITE) {
+-                      pr_warn("%s incorrect op %d req %p index %d tid %llu\n",
+-                              __func__, req->r_ops[i].op, req, i, req->r_tid);
++                      pr_warn_client(cl,
++                              "%llx.%llx incorrect op %d req %p index %d tid %llu\n",
++                              ceph_vinop(inode), req->r_ops[i].op, req, i,
++                              req->r_tid);
+                       break;
+               }
+@@ -896,7 +910,7 @@ static void writepages_finish(struct cep
+                       ceph_put_snap_context(detach_page_private(page));
+                       end_page_writeback(page);
+-                      dout("unlocking %p\n", page);
++                      doutc(cl, "unlocking %p\n", page);
+                       if (remove_page)
+                               generic_error_remove_page(inode->i_mapping,
+@@ -904,8 +918,9 @@ static void writepages_finish(struct cep
+                       unlock_page(page);
+               }
+-              dout("writepages_finish %p wrote %llu bytes cleaned %d pages\n",
+-                   inode, osd_data->length, rc >= 0 ? num_pages : 0);
++              doutc(cl, "%llx.%llx wrote %llu bytes cleaned %d pages\n",
++                    ceph_vinop(inode), osd_data->length,
++                    rc >= 0 ? num_pages : 0);
+               release_pages(osd_data->pages, num_pages);
+       }
+@@ -933,6 +948,7 @@ static int ceph_writepages_start(struct
+       struct inode *inode = mapping->host;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_vino vino = ceph_vino(inode);
+       pgoff_t index, start_index, end = -1;
+       struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc;
+@@ -950,15 +966,15 @@ static int ceph_writepages_start(struct
+           fsc->write_congested)
+               return 0;
+-      dout("writepages_start %p (mode=%s)\n", inode,
+-           wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
+-           (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
++      doutc(cl, "%llx.%llx (mode=%s)\n", ceph_vinop(inode),
++            wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
++            (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
+       if (ceph_inode_is_shutdown(inode)) {
+               if (ci->i_wrbuffer_ref > 0) {
+-                      pr_warn_ratelimited(
+-                              "writepage_start %p %lld forced umount\n",
+-                              inode, ceph_ino(inode));
++                      pr_warn_ratelimited_client(cl,
++                              "%llx.%llx %lld forced umount\n",
++                              ceph_vinop(inode), ceph_ino(inode));
+               }
+               mapping_set_error(mapping, -EIO);
+               return -EIO; /* we're in a forced umount, don't write! */
+@@ -982,11 +998,11 @@ retry:
+       if (!snapc) {
+               /* hmm, why does writepages get called when there
+                  is no dirty data? */
+-              dout(" no snap context with dirty data?\n");
++              doutc(cl, " no snap context with dirty data?\n");
+               goto out;
+       }
+-      dout(" oldest snapc is %p seq %lld (%d snaps)\n",
+-           snapc, snapc->seq, snapc->num_snaps);
++      doutc(cl, " oldest snapc is %p seq %lld (%d snaps)\n", snapc,
++            snapc->seq, snapc->num_snaps);
+       should_loop = false;
+       if (ceph_wbc.head_snapc && snapc != last_snapc) {
+@@ -996,13 +1012,13 @@ retry:
+                       end = -1;
+                       if (index > 0)
+                               should_loop = true;
+-                      dout(" cyclic, start at %lu\n", index);
++                      doutc(cl, " cyclic, start at %lu\n", index);
+               } else {
+                       index = wbc->range_start >> PAGE_SHIFT;
+                       end = wbc->range_end >> PAGE_SHIFT;
+                       if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+                               range_whole = true;
+-                      dout(" not cyclic, %lu to %lu\n", index, end);
++                      doutc(cl, " not cyclic, %lu to %lu\n", index, end);
+               }
+       } else if (!ceph_wbc.head_snapc) {
+               /* Do not respect wbc->range_{start,end}. Dirty pages
+@@ -1011,7 +1027,7 @@ retry:
+                * associated with 'snapc' get written */
+               if (index > 0)
+                       should_loop = true;
+-              dout(" non-head snapc, range whole\n");
++              doutc(cl, " non-head snapc, range whole\n");
+       }
+       if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
+@@ -1034,12 +1050,12 @@ retry:
+ get_more_pages:
+               nr_folios = filemap_get_folios_tag(mapping, &index,
+                                                  end, tag, &fbatch);
+-              dout("pagevec_lookup_range_tag got %d\n", nr_folios);
++              doutc(cl, "pagevec_lookup_range_tag got %d\n", nr_folios);
+               if (!nr_folios && !locked_pages)
+                       break;
+               for (i = 0; i < nr_folios && locked_pages < max_pages; i++) {
+                       page = &fbatch.folios[i]->page;
+-                      dout("? %p idx %lu\n", page, page->index);
++                      doutc(cl, "? %p idx %lu\n", page, page->index);
+                       if (locked_pages == 0)
+                               lock_page(page);  /* first page */
+                       else if (!trylock_page(page))
+@@ -1048,15 +1064,15 @@ get_more_pages:
+                       /* only dirty pages, or our accounting breaks */
+                       if (unlikely(!PageDirty(page)) ||
+                           unlikely(page->mapping != mapping)) {
+-                              dout("!dirty or !mapping %p\n", page);
++                              doutc(cl, "!dirty or !mapping %p\n", page);
+                               unlock_page(page);
+                               continue;
+                       }
+                       /* only if matching snap context */
+                       pgsnapc = page_snap_context(page);
+                       if (pgsnapc != snapc) {
+-                              dout("page snapc %p %lld != oldest %p %lld\n",
+-                                   pgsnapc, pgsnapc->seq, snapc, snapc->seq);
++                              doutc(cl, "page snapc %p %lld != oldest %p %lld\n",
++                                    pgsnapc, pgsnapc->seq, snapc, snapc->seq);
+                               if (!should_loop &&
+                                   !ceph_wbc.head_snapc &&
+                                   wbc->sync_mode != WB_SYNC_NONE)
+@@ -1067,8 +1083,8 @@ get_more_pages:
+                       if (page_offset(page) >= ceph_wbc.i_size) {
+                               struct folio *folio = page_folio(page);
+-                              dout("folio at %lu beyond eof %llu\n",
+-                                   folio->index, ceph_wbc.i_size);
++                              doutc(cl, "folio at %lu beyond eof %llu\n",
++                                    folio->index, ceph_wbc.i_size);
+                               if ((ceph_wbc.size_stable ||
+                                   folio_pos(folio) >= i_size_read(inode)) &&
+                                   folio_clear_dirty_for_io(folio))
+@@ -1078,23 +1094,23 @@ get_more_pages:
+                               continue;
+                       }
+                       if (strip_unit_end && (page->index > strip_unit_end)) {
+-                              dout("end of strip unit %p\n", page);
++                              doutc(cl, "end of strip unit %p\n", page);
+                               unlock_page(page);
+                               break;
+                       }
+                       if (PageWriteback(page) || PageFsCache(page)) {
+                               if (wbc->sync_mode == WB_SYNC_NONE) {
+-                                      dout("%p under writeback\n", page);
++                                      doutc(cl, "%p under writeback\n", page);
+                                       unlock_page(page);
+                                       continue;
+                               }
+-                              dout("waiting on writeback %p\n", page);
++                              doutc(cl, "waiting on writeback %p\n", page);
+                               wait_on_page_writeback(page);
+                               wait_on_page_fscache(page);
+                       }
+                       if (!clear_page_dirty_for_io(page)) {
+-                              dout("%p !clear_page_dirty_for_io\n", page);
++                              doutc(cl, "%p !clear_page_dirty_for_io\n", page);
+                               unlock_page(page);
+                               continue;
+                       }
+@@ -1149,8 +1165,8 @@ get_more_pages:
+                       }
+                       /* note position of first page in fbatch */
+-                      dout("%p will write page %p idx %lu\n",
+-                           inode, page, page->index);
++                      doutc(cl, "%llx.%llx will write page %p idx %lu\n",
++                            ceph_vinop(inode), page, page->index);
+                       if (atomic_long_inc_return(&fsc->writeback_count) >
+                           CONGESTION_ON_THRESH(
+@@ -1164,8 +1180,9 @@ get_more_pages:
+                                               locked_pages ? GFP_NOWAIT : GFP_NOFS);
+                               if (IS_ERR(pages[locked_pages])) {
+                                       if (PTR_ERR(pages[locked_pages]) == -EINVAL)
+-                                              pr_err("%s: inode->i_blkbits=%hhu\n",
+-                                                      __func__, inode->i_blkbits);
++                                              pr_err_client(cl,
++                                                      "inode->i_blkbits=%hhu\n",
++                                                      inode->i_blkbits);
+                                       /* better not fail on first page! */
+                                       BUG_ON(locked_pages == 0);
+                                       pages[locked_pages] = NULL;
+@@ -1199,7 +1216,7 @@ get_more_pages:
+                       if (nr_folios && i == nr_folios &&
+                           locked_pages < max_pages) {
+-                              dout("reached end fbatch, trying for more\n");
++                              doutc(cl, "reached end fbatch, trying for more\n");
+                               folio_batch_release(&fbatch);
+                               goto get_more_pages;
+                       }
+@@ -1260,8 +1277,8 @@ new_request:
+                               /* Start a new extent */
+                               osd_req_op_extent_dup_last(req, op_idx,
+                                                          cur_offset - offset);
+-                              dout("writepages got pages at %llu~%llu\n",
+-                                   offset, len);
++                              doutc(cl, "got pages at %llu~%llu\n", offset,
++                                    len);
+                               osd_req_op_extent_osd_data_pages(req, op_idx,
+                                                       data_pages, len, 0,
+                                                       from_pool, false);
+@@ -1294,12 +1311,13 @@ new_request:
+               if (IS_ENCRYPTED(inode))
+                       len = round_up(len, CEPH_FSCRYPT_BLOCK_SIZE);
+-              dout("writepages got pages at %llu~%llu\n", offset, len);
++              doutc(cl, "got pages at %llu~%llu\n", offset, len);
+               if (IS_ENCRYPTED(inode) &&
+                   ((offset | len) & ~CEPH_FSCRYPT_BLOCK_MASK))
+-                      pr_warn("%s: bad encrypted write offset=%lld len=%llu\n",
+-                              __func__, offset, len);
++                      pr_warn_client(cl,
++                              "bad encrypted write offset=%lld len=%llu\n",
++                              offset, len);
+               osd_req_op_extent_osd_data_pages(req, op_idx, data_pages, len,
+                                                0, from_pool, false);
+@@ -1351,14 +1369,14 @@ new_request:
+                       done = true;
+ release_folios:
+-              dout("folio_batch release on %d folios (%p)\n", (int)fbatch.nr,
+-                   fbatch.nr ? fbatch.folios[0] : NULL);
++              doutc(cl, "folio_batch release on %d folios (%p)\n",
++                    (int)fbatch.nr, fbatch.nr ? fbatch.folios[0] : NULL);
+               folio_batch_release(&fbatch);
+       }
+       if (should_loop && !done) {
+               /* more to do; loop back to beginning of file */
+-              dout("writepages looping back to beginning of file\n");
++              doutc(cl, "looping back to beginning of file\n");
+               end = start_index - 1; /* OK even when start_index == 0 */
+               /* to write dirty pages associated with next snapc,
+@@ -1396,7 +1414,8 @@ release_folios:
+ out:
+       ceph_osdc_put_request(req);
+       ceph_put_snap_context(last_snapc);
+-      dout("writepages dend - startone, rc = %d\n", rc);
++      doutc(cl, "%llx.%llx dend - startone, rc = %d\n", ceph_vinop(inode),
++            rc);
+       return rc;
+ }
+@@ -1430,11 +1449,12 @@ static struct ceph_snap_context *
+ ceph_find_incompatible(struct page *page)
+ {
+       struct inode *inode = page->mapping->host;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       if (ceph_inode_is_shutdown(inode)) {
+-              dout(" page %p %llx:%llx is shutdown\n", page,
+-                   ceph_vinop(inode));
++              doutc(cl, " %llx.%llx page %p is shutdown\n",
++                    ceph_vinop(inode), page);
+               return ERR_PTR(-ESTALE);
+       }
+@@ -1455,13 +1475,15 @@ ceph_find_incompatible(struct page *page
+               if (snapc->seq > oldest->seq) {
+                       /* not writeable -- return it for the caller to deal with */
+                       ceph_put_snap_context(oldest);
+-                      dout(" page %p snapc %p not current or oldest\n", page, snapc);
++                      doutc(cl, " %llx.%llx page %p snapc %p not current or oldest\n",
++                            ceph_vinop(inode), page, snapc);
+                       return ceph_get_snap_context(snapc);
+               }
+               ceph_put_snap_context(oldest);
+               /* yay, writeable, do it now (without dropping page lock) */
+-              dout(" page %p snapc %p not current, but oldest\n", page, snapc);
++              doutc(cl, " %llx.%llx page %p snapc %p not current, but oldest\n",
++                    ceph_vinop(inode), page, snapc);
+               if (clear_page_dirty_for_io(page)) {
+                       int r = writepage_nounlock(page, NULL);
+                       if (r < 0)
+@@ -1530,10 +1552,11 @@ static int ceph_write_end(struct file *f
+ {
+       struct folio *folio = page_folio(subpage);
+       struct inode *inode = file_inode(file);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       bool check_cap = false;
+-      dout("write_end file %p inode %p folio %p %d~%d (%d)\n", file,
+-           inode, folio, (int)pos, (int)copied, (int)len);
++      doutc(cl, "%llx.%llx file %p folio %p %d~%d (%d)\n", ceph_vinop(inode),
++            file, folio, (int)pos, (int)copied, (int)len);
+       if (!folio_test_uptodate(folio)) {
+               /* just return that nothing was copied on a short copy */
+@@ -1593,6 +1616,7 @@ static vm_fault_t ceph_filemap_fault(str
+       struct vm_area_struct *vma = vmf->vma;
+       struct inode *inode = file_inode(vma->vm_file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_file_info *fi = vma->vm_file->private_data;
+       loff_t off = (loff_t)vmf->pgoff << PAGE_SHIFT;
+       int want, got, err;
+@@ -1604,8 +1628,8 @@ static vm_fault_t ceph_filemap_fault(str
+       ceph_block_sigs(&oldset);
+-      dout("filemap_fault %p %llx.%llx %llu trying to get caps\n",
+-           inode, ceph_vinop(inode), off);
++      doutc(cl, "%llx.%llx %llu trying to get caps\n",
++            ceph_vinop(inode), off);
+       if (fi->fmode & CEPH_FILE_MODE_LAZY)
+               want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
+       else
+@@ -1616,8 +1640,8 @@ static vm_fault_t ceph_filemap_fault(str
+       if (err < 0)
+               goto out_restore;
+-      dout("filemap_fault %p %llu got cap refs on %s\n",
+-           inode, off, ceph_cap_string(got));
++      doutc(cl, "%llx.%llx %llu got cap refs on %s\n", ceph_vinop(inode),
++            off, ceph_cap_string(got));
+       if ((got & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) ||
+           !ceph_has_inline_data(ci)) {
+@@ -1625,8 +1649,8 @@ static vm_fault_t ceph_filemap_fault(str
+               ceph_add_rw_context(fi, &rw_ctx);
+               ret = filemap_fault(vmf);
+               ceph_del_rw_context(fi, &rw_ctx);
+-              dout("filemap_fault %p %llu drop cap refs %s ret %x\n",
+-                   inode, off, ceph_cap_string(got), ret);
++              doutc(cl, "%llx.%llx %llu drop cap refs %s ret %x\n",
++                    ceph_vinop(inode), off, ceph_cap_string(got), ret);
+       } else
+               err = -EAGAIN;
+@@ -1667,8 +1691,8 @@ static vm_fault_t ceph_filemap_fault(str
+               ret = VM_FAULT_MAJOR | VM_FAULT_LOCKED;
+ out_inline:
+               filemap_invalidate_unlock_shared(mapping);
+-              dout("filemap_fault %p %llu read inline data ret %x\n",
+-                   inode, off, ret);
++              doutc(cl, "%llx.%llx %llu read inline data ret %x\n",
++                    ceph_vinop(inode), off, ret);
+       }
+ out_restore:
+       ceph_restore_sigs(&oldset);
+@@ -1682,6 +1706,7 @@ static vm_fault_t ceph_page_mkwrite(stru
+ {
+       struct vm_area_struct *vma = vmf->vma;
+       struct inode *inode = file_inode(vma->vm_file);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_file_info *fi = vma->vm_file->private_data;
+       struct ceph_cap_flush *prealloc_cf;
+@@ -1708,8 +1733,8 @@ static vm_fault_t ceph_page_mkwrite(stru
+       else
+               len = offset_in_thp(page, size);
+-      dout("page_mkwrite %p %llx.%llx %llu~%zd getting caps i_size %llu\n",
+-           inode, ceph_vinop(inode), off, len, size);
++      doutc(cl, "%llx.%llx %llu~%zd getting caps i_size %llu\n",
++            ceph_vinop(inode), off, len, size);
+       if (fi->fmode & CEPH_FILE_MODE_LAZY)
+               want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
+       else
+@@ -1720,8 +1745,8 @@ static vm_fault_t ceph_page_mkwrite(stru
+       if (err < 0)
+               goto out_free;
+-      dout("page_mkwrite %p %llu~%zd got cap refs on %s\n",
+-           inode, off, len, ceph_cap_string(got));
++      doutc(cl, "%llx.%llx %llu~%zd got cap refs on %s\n", ceph_vinop(inode),
++            off, len, ceph_cap_string(got));
+       /* Update time before taking page lock */
+       file_update_time(vma->vm_file);
+@@ -1769,8 +1794,8 @@ static vm_fault_t ceph_page_mkwrite(stru
+                       __mark_inode_dirty(inode, dirty);
+       }
+-      dout("page_mkwrite %p %llu~%zd dropping cap refs on %s ret %x\n",
+-           inode, off, len, ceph_cap_string(got), ret);
++      doutc(cl, "%llx.%llx %llu~%zd dropping cap refs on %s ret %x\n",
++            ceph_vinop(inode), off, len, ceph_cap_string(got), ret);
+       ceph_put_cap_refs_async(ci, got);
+ out_free:
+       ceph_restore_sigs(&oldset);
+@@ -1784,6 +1809,7 @@ out_free:
+ void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
+                          char *data, size_t len)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct address_space *mapping = inode->i_mapping;
+       struct page *page;
+@@ -1804,8 +1830,8 @@ void ceph_fill_inline_data(struct inode
+               }
+       }
+-      dout("fill_inline_data %p %llx.%llx len %zu locked_page %p\n",
+-           inode, ceph_vinop(inode), len, locked_page);
++      doutc(cl, "%p %llx.%llx len %zu locked_page %p\n", inode,
++            ceph_vinop(inode), len, locked_page);
+       if (len > 0) {
+               void *kaddr = kmap_atomic(page);
+@@ -1830,6 +1856,7 @@ int ceph_uninline_data(struct file *file
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_osd_request *req = NULL;
+       struct ceph_cap_flush *prealloc_cf = NULL;
+       struct folio *folio = NULL;
+@@ -1843,8 +1870,8 @@ int ceph_uninline_data(struct file *file
+       inline_version = ci->i_inline_version;
+       spin_unlock(&ci->i_ceph_lock);
+-      dout("uninline_data %p %llx.%llx inline_version %llu\n",
+-           inode, ceph_vinop(inode), inline_version);
++      doutc(cl, "%llx.%llx inline_version %llu\n", ceph_vinop(inode),
++            inline_version);
+       if (ceph_inode_is_shutdown(inode)) {
+               err = -EIO;
+@@ -1975,8 +2002,8 @@ out_unlock:
+ out:
+       ceph_put_snap_context(snapc);
+       ceph_free_cap_flush(prealloc_cf);
+-      dout("uninline_data %p %llx.%llx inline_version %llu = %d\n",
+-           inode, ceph_vinop(inode), inline_version, err);
++      doutc(cl, "%llx.%llx inline_version %llu = %d\n",
++            ceph_vinop(inode), inline_version, err);
+       return err;
+ }
+@@ -2005,6 +2032,7 @@ static int __ceph_pool_perm_get(struct c
+ {
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(&ci->netfs.inode);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
++      struct ceph_client *cl = fsc->client;
+       struct ceph_osd_request *rd_req = NULL, *wr_req = NULL;
+       struct rb_node **p, *parent;
+       struct ceph_pool_perm *perm;
+@@ -2039,10 +2067,10 @@ static int __ceph_pool_perm_get(struct c
+               goto out;
+       if (pool_ns)
+-              dout("__ceph_pool_perm_get pool %lld ns %.*s no perm cached\n",
+-                   pool, (int)pool_ns->len, pool_ns->str);
++              doutc(cl, "pool %lld ns %.*s no perm cached\n", pool,
++                    (int)pool_ns->len, pool_ns->str);
+       else
+-              dout("__ceph_pool_perm_get pool %lld no perm cached\n", pool);
++              doutc(cl, "pool %lld no perm cached\n", pool);
+       down_write(&mdsc->pool_perm_rwsem);
+       p = &mdsc->pool_perm_tree.rb_node;
+@@ -2167,15 +2195,16 @@ out:
+       if (!err)
+               err = have;
+       if (pool_ns)
+-              dout("__ceph_pool_perm_get pool %lld ns %.*s result = %d\n",
+-                   pool, (int)pool_ns->len, pool_ns->str, err);
++              doutc(cl, "pool %lld ns %.*s result = %d\n", pool,
++                    (int)pool_ns->len, pool_ns->str, err);
+       else
+-              dout("__ceph_pool_perm_get pool %lld result = %d\n", pool, err);
++              doutc(cl, "pool %lld result = %d\n", pool, err);
+       return err;
+ }
+ int ceph_pool_perm_check(struct inode *inode, int need)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_string *pool_ns;
+       s64 pool;
+@@ -2205,13 +2234,11 @@ int ceph_pool_perm_check(struct inode *i
+ check:
+       if (flags & CEPH_I_POOL_PERM) {
+               if ((need & CEPH_CAP_FILE_RD) && !(flags & CEPH_I_POOL_RD)) {
+-                      dout("ceph_pool_perm_check pool %lld no read perm\n",
+-                           pool);
++                      doutc(cl, "pool %lld no read perm\n", pool);
+                       return -EPERM;
+               }
+               if ((need & CEPH_CAP_FILE_WR) && !(flags & CEPH_I_POOL_WR)) {
+-                      dout("ceph_pool_perm_check pool %lld no write perm\n",
+-                           pool);
++                      doutc(cl, "pool %lld no write perm\n", pool);
+                       return -EPERM;
+               }
+               return 0;
+--- a/fs/ceph/caps.c
++++ b/fs/ceph/caps.c
+@@ -186,10 +186,10 @@ static void __ceph_unreserve_caps(struct
+                       mdsc->caps_avail_count += nr_caps;
+               }
+-              dout("%s: caps %d = %d used + %d resv + %d avail\n",
+-                   __func__,
+-                   mdsc->caps_total_count, mdsc->caps_use_count,
+-                   mdsc->caps_reserve_count, mdsc->caps_avail_count);
++              doutc(mdsc->fsc->client,
++                    "caps %d = %d used + %d resv + %d avail\n",
++                    mdsc->caps_total_count, mdsc->caps_use_count,
++                    mdsc->caps_reserve_count, mdsc->caps_avail_count);
+               BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count +
+                                                mdsc->caps_reserve_count +
+                                                mdsc->caps_avail_count);
+@@ -202,6 +202,7 @@ static void __ceph_unreserve_caps(struct
+ int ceph_reserve_caps(struct ceph_mds_client *mdsc,
+                     struct ceph_cap_reservation *ctx, int need)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int i, j;
+       struct ceph_cap *cap;
+       int have;
+@@ -212,7 +213,7 @@ int ceph_reserve_caps(struct ceph_mds_cl
+       struct ceph_mds_session *s;
+       LIST_HEAD(newcaps);
+-      dout("reserve caps ctx=%p need=%d\n", ctx, need);
++      doutc(cl, "ctx=%p need=%d\n", ctx, need);
+       /* first reserve any caps that are already allocated */
+       spin_lock(&mdsc->caps_list_lock);
+@@ -272,8 +273,8 @@ int ceph_reserve_caps(struct ceph_mds_cl
+                       continue;
+               }
+-              pr_warn("reserve caps ctx=%p ENOMEM need=%d got=%d\n",
+-                      ctx, need, have + alloc);
++              pr_warn_client(cl, "ctx=%p ENOMEM need=%d got=%d\n", ctx, need,
++                             have + alloc);
+               err = -ENOMEM;
+               break;
+       }
+@@ -298,20 +299,21 @@ int ceph_reserve_caps(struct ceph_mds_cl
+       spin_unlock(&mdsc->caps_list_lock);
+-      dout("reserve caps ctx=%p %d = %d used + %d resv + %d avail\n",
+-           ctx, mdsc->caps_total_count, mdsc->caps_use_count,
+-           mdsc->caps_reserve_count, mdsc->caps_avail_count);
++      doutc(cl, "ctx=%p %d = %d used + %d resv + %d avail\n", ctx,
++            mdsc->caps_total_count, mdsc->caps_use_count,
++            mdsc->caps_reserve_count, mdsc->caps_avail_count);
+       return err;
+ }
+ void ceph_unreserve_caps(struct ceph_mds_client *mdsc,
+                        struct ceph_cap_reservation *ctx)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       bool reclaim = false;
+       if (!ctx->count)
+               return;
+-      dout("unreserve caps ctx=%p count=%d\n", ctx, ctx->count);
++      doutc(cl, "ctx=%p count=%d\n", ctx, ctx->count);
+       spin_lock(&mdsc->caps_list_lock);
+       __ceph_unreserve_caps(mdsc, ctx->count);
+       ctx->count = 0;
+@@ -328,6 +330,7 @@ void ceph_unreserve_caps(struct ceph_mds
+ struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
+                             struct ceph_cap_reservation *ctx)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_cap *cap = NULL;
+       /* temporary, until we do something about cap import/export */
+@@ -359,9 +362,9 @@ struct ceph_cap *ceph_get_cap(struct cep
+       }
+       spin_lock(&mdsc->caps_list_lock);
+-      dout("get_cap ctx=%p (%d) %d = %d used + %d resv + %d avail\n",
+-           ctx, ctx->count, mdsc->caps_total_count, mdsc->caps_use_count,
+-           mdsc->caps_reserve_count, mdsc->caps_avail_count);
++      doutc(cl, "ctx=%p (%d) %d = %d used + %d resv + %d avail\n", ctx,
++            ctx->count, mdsc->caps_total_count, mdsc->caps_use_count,
++            mdsc->caps_reserve_count, mdsc->caps_avail_count);
+       BUG_ON(!ctx->count);
+       BUG_ON(ctx->count > mdsc->caps_reserve_count);
+       BUG_ON(list_empty(&mdsc->caps_list));
+@@ -382,10 +385,12 @@ struct ceph_cap *ceph_get_cap(struct cep
+ void ceph_put_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
++
+       spin_lock(&mdsc->caps_list_lock);
+-      dout("put_cap %p %d = %d used + %d resv + %d avail\n",
+-           cap, mdsc->caps_total_count, mdsc->caps_use_count,
+-           mdsc->caps_reserve_count, mdsc->caps_avail_count);
++      doutc(cl, "%p %d = %d used + %d resv + %d avail\n", cap,
++            mdsc->caps_total_count, mdsc->caps_use_count,
++            mdsc->caps_reserve_count, mdsc->caps_avail_count);
+       mdsc->caps_use_count--;
+       /*
+        * Keep some preallocated caps around (ceph_min_count), to
+@@ -491,11 +496,13 @@ static void __insert_cap_node(struct cep
+ static void __cap_set_timeouts(struct ceph_mds_client *mdsc,
+                              struct ceph_inode_info *ci)
+ {
++      struct inode *inode = &ci->netfs.inode;
+       struct ceph_mount_options *opt = mdsc->fsc->mount_options;
++
+       ci->i_hold_caps_max = round_jiffies(jiffies +
+                                           opt->caps_wanted_delay_max * HZ);
+-      dout("__cap_set_timeouts %p %lu\n", &ci->netfs.inode,
+-           ci->i_hold_caps_max - jiffies);
++      doutc(mdsc->fsc->client, "%p %llx.%llx %lu\n", inode,
++            ceph_vinop(inode), ci->i_hold_caps_max - jiffies);
+ }
+ /*
+@@ -509,8 +516,11 @@ static void __cap_set_timeouts(struct ce
+ static void __cap_delay_requeue(struct ceph_mds_client *mdsc,
+                               struct ceph_inode_info *ci)
+ {
+-      dout("__cap_delay_requeue %p flags 0x%lx at %lu\n", &ci->netfs.inode,
+-           ci->i_ceph_flags, ci->i_hold_caps_max);
++      struct inode *inode = &ci->netfs.inode;
++
++      doutc(mdsc->fsc->client, "%p %llx.%llx flags 0x%lx at %lu\n",
++            inode, ceph_vinop(inode), ci->i_ceph_flags,
++            ci->i_hold_caps_max);
+       if (!mdsc->stopping) {
+               spin_lock(&mdsc->cap_delay_lock);
+               if (!list_empty(&ci->i_cap_delay_list)) {
+@@ -533,7 +543,9 @@ no_change:
+ static void __cap_delay_requeue_front(struct ceph_mds_client *mdsc,
+                                     struct ceph_inode_info *ci)
+ {
+-      dout("__cap_delay_requeue_front %p\n", &ci->netfs.inode);
++      struct inode *inode = &ci->netfs.inode;
++
++      doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode, ceph_vinop(inode));
+       spin_lock(&mdsc->cap_delay_lock);
+       ci->i_ceph_flags |= CEPH_I_FLUSH;
+       if (!list_empty(&ci->i_cap_delay_list))
+@@ -550,7 +562,9 @@ static void __cap_delay_requeue_front(st
+ static void __cap_delay_cancel(struct ceph_mds_client *mdsc,
+                              struct ceph_inode_info *ci)
+ {
+-      dout("__cap_delay_cancel %p\n", &ci->netfs.inode);
++      struct inode *inode = &ci->netfs.inode;
++
++      doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode, ceph_vinop(inode));
+       if (list_empty(&ci->i_cap_delay_list))
+               return;
+       spin_lock(&mdsc->cap_delay_lock);
+@@ -562,6 +576,9 @@ static void __cap_delay_cancel(struct ce
+ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
+                             unsigned issued)
+ {
++      struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
++
+       unsigned had = __ceph_caps_issued(ci, NULL);
+       lockdep_assert_held(&ci->i_ceph_lock);
+@@ -586,7 +603,7 @@ static void __check_cap_issue(struct cep
+               if (issued & CEPH_CAP_FILE_SHARED)
+                       atomic_inc(&ci->i_shared_gen);
+               if (S_ISDIR(ci->netfs.inode.i_mode)) {
+-                      dout(" marking %p NOT complete\n", &ci->netfs.inode);
++                      doutc(cl, " marking %p NOT complete\n", inode);
+                       __ceph_dir_clear_complete(ci);
+               }
+       }
+@@ -636,6 +653,7 @@ void ceph_add_cap(struct inode *inode,
+                 struct ceph_cap **new_cap)
+ {
+       struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_cap *cap;
+       int mds = session->s_mds;
+@@ -644,8 +662,9 @@ void ceph_add_cap(struct inode *inode,
+       lockdep_assert_held(&ci->i_ceph_lock);
+-      dout("add_cap %p mds%d cap %llx %s seq %d\n", inode,
+-           session->s_mds, cap_id, ceph_cap_string(issued), seq);
++      doutc(cl, "%p %llx.%llx mds%d cap %llx %s seq %d\n", inode,
++            ceph_vinop(inode), session->s_mds, cap_id,
++            ceph_cap_string(issued), seq);
+       gen = atomic_read(&session->s_cap_gen);
+@@ -723,9 +742,9 @@ void ceph_add_cap(struct inode *inode,
+       actual_wanted = __ceph_caps_wanted(ci);
+       if ((wanted & ~actual_wanted) ||
+           (issued & ~actual_wanted & CEPH_CAP_ANY_WR)) {
+-              dout(" issued %s, mds wanted %s, actual %s, queueing\n",
+-                   ceph_cap_string(issued), ceph_cap_string(wanted),
+-                   ceph_cap_string(actual_wanted));
++              doutc(cl, "issued %s, mds wanted %s, actual %s, queueing\n",
++                    ceph_cap_string(issued), ceph_cap_string(wanted),
++                    ceph_cap_string(actual_wanted));
+               __cap_delay_requeue(mdsc, ci);
+       }
+@@ -742,9 +761,9 @@ void ceph_add_cap(struct inode *inode,
+               WARN_ON(ci->i_auth_cap == cap);
+       }
+-      dout("add_cap inode %p (%llx.%llx) cap %p %s now %s seq %d mds%d\n",
+-           inode, ceph_vinop(inode), cap, ceph_cap_string(issued),
+-           ceph_cap_string(issued|cap->issued), seq, mds);
++      doutc(cl, "inode %p %llx.%llx cap %p %s now %s seq %d mds%d\n",
++            inode, ceph_vinop(inode), cap, ceph_cap_string(issued),
++            ceph_cap_string(issued|cap->issued), seq, mds);
+       cap->cap_id = cap_id;
+       cap->issued = issued;
+       cap->implemented |= issued;
+@@ -766,6 +785,8 @@ void ceph_add_cap(struct inode *inode,
+  */
+ static int __cap_is_valid(struct ceph_cap *cap)
+ {
++      struct inode *inode = &cap->ci->netfs.inode;
++      struct ceph_client *cl = cap->session->s_mdsc->fsc->client;
+       unsigned long ttl;
+       u32 gen;
+@@ -773,9 +794,9 @@ static int __cap_is_valid(struct ceph_ca
+       ttl = cap->session->s_cap_ttl;
+       if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) {
+-              dout("__cap_is_valid %p cap %p issued %s "
+-                   "but STALE (gen %u vs %u)\n", &cap->ci->netfs.inode,
+-                   cap, ceph_cap_string(cap->issued), cap->cap_gen, gen);
++              doutc(cl, "%p %llx.%llx cap %p issued %s but STALE (gen %u vs %u)\n",
++                    inode, ceph_vinop(inode), cap,
++                    ceph_cap_string(cap->issued), cap->cap_gen, gen);
+               return 0;
+       }
+@@ -789,6 +810,8 @@ static int __cap_is_valid(struct ceph_ca
+  */
+ int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented)
+ {
++      struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int have = ci->i_snap_caps;
+       struct ceph_cap *cap;
+       struct rb_node *p;
+@@ -799,8 +822,8 @@ int __ceph_caps_issued(struct ceph_inode
+               cap = rb_entry(p, struct ceph_cap, ci_node);
+               if (!__cap_is_valid(cap))
+                       continue;
+-              dout("__ceph_caps_issued %p cap %p issued %s\n",
+-                   &ci->netfs.inode, cap, ceph_cap_string(cap->issued));
++              doutc(cl, "%p %llx.%llx cap %p issued %s\n", inode,
++                    ceph_vinop(inode), cap, ceph_cap_string(cap->issued));
+               have |= cap->issued;
+               if (implemented)
+                       *implemented |= cap->implemented;
+@@ -843,16 +866,18 @@ int __ceph_caps_issued_other(struct ceph
+  */
+ static void __touch_cap(struct ceph_cap *cap)
+ {
++      struct inode *inode = &cap->ci->netfs.inode;
+       struct ceph_mds_session *s = cap->session;
++      struct ceph_client *cl = s->s_mdsc->fsc->client;
+       spin_lock(&s->s_cap_lock);
+       if (!s->s_cap_iterator) {
+-              dout("__touch_cap %p cap %p mds%d\n", &cap->ci->netfs.inode, cap,
+-                   s->s_mds);
++              doutc(cl, "%p %llx.%llx cap %p mds%d\n", inode,
++                    ceph_vinop(inode), cap, s->s_mds);
+               list_move_tail(&cap->session_caps, &s->s_caps);
+       } else {
+-              dout("__touch_cap %p cap %p mds%d NOP, iterating over caps\n",
+-                   &cap->ci->netfs.inode, cap, s->s_mds);
++              doutc(cl, "%p %llx.%llx cap %p mds%d NOP, iterating over caps\n",
++                    inode, ceph_vinop(inode), cap, s->s_mds);
+       }
+       spin_unlock(&s->s_cap_lock);
+ }
+@@ -864,15 +889,16 @@ static void __touch_cap(struct ceph_cap
+  */
+ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
+ {
++      struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_cap *cap;
+       struct rb_node *p;
+       int have = ci->i_snap_caps;
+       if ((have & mask) == mask) {
+-              dout("__ceph_caps_issued_mask ino 0x%llx snap issued %s"
+-                   " (mask %s)\n", ceph_ino(&ci->netfs.inode),
+-                   ceph_cap_string(have),
+-                   ceph_cap_string(mask));
++              doutc(cl, "mask %p %llx.%llx snap issued %s (mask %s)\n",
++                    inode, ceph_vinop(inode), ceph_cap_string(have),
++                    ceph_cap_string(mask));
+               return 1;
+       }
+@@ -881,10 +907,10 @@ int __ceph_caps_issued_mask(struct ceph_
+               if (!__cap_is_valid(cap))
+                       continue;
+               if ((cap->issued & mask) == mask) {
+-                      dout("__ceph_caps_issued_mask ino 0x%llx cap %p issued %s"
+-                           " (mask %s)\n", ceph_ino(&ci->netfs.inode), cap,
+-                           ceph_cap_string(cap->issued),
+-                           ceph_cap_string(mask));
++                      doutc(cl, "mask %p %llx.%llx cap %p issued %s (mask %s)\n",
++                            inode, ceph_vinop(inode), cap,
++                            ceph_cap_string(cap->issued),
++                            ceph_cap_string(mask));
+                       if (touch)
+                               __touch_cap(cap);
+                       return 1;
+@@ -893,10 +919,10 @@ int __ceph_caps_issued_mask(struct ceph_
+               /* does a combination of caps satisfy mask? */
+               have |= cap->issued;
+               if ((have & mask) == mask) {
+-                      dout("__ceph_caps_issued_mask ino 0x%llx combo issued %s"
+-                           " (mask %s)\n", ceph_ino(&ci->netfs.inode),
+-                           ceph_cap_string(cap->issued),
+-                           ceph_cap_string(mask));
++                      doutc(cl, "mask %p %llx.%llx combo issued %s (mask %s)\n",
++                            inode, ceph_vinop(inode),
++                            ceph_cap_string(cap->issued),
++                            ceph_cap_string(mask));
+                       if (touch) {
+                               struct rb_node *q;
+@@ -954,13 +980,14 @@ int __ceph_caps_revoking_other(struct ce
+ int ceph_caps_revoking(struct ceph_inode_info *ci, int mask)
+ {
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int ret;
+       spin_lock(&ci->i_ceph_lock);
+       ret = __ceph_caps_revoking_other(ci, NULL, mask);
+       spin_unlock(&ci->i_ceph_lock);
+-      dout("ceph_caps_revoking %p %s = %d\n", inode,
+-           ceph_cap_string(mask), ret);
++      doutc(cl, "%p %llx.%llx %s = %d\n", inode, ceph_vinop(inode),
++            ceph_cap_string(mask), ret);
+       return ret;
+ }
+@@ -1107,19 +1134,21 @@ int ceph_is_any_caps(struct inode *inode
+ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
+ {
+       struct ceph_mds_session *session = cap->session;
++      struct ceph_client *cl = session->s_mdsc->fsc->client;
+       struct ceph_inode_info *ci = cap->ci;
++      struct inode *inode = &ci->netfs.inode;
+       struct ceph_mds_client *mdsc;
+       int removed = 0;
+       /* 'ci' being NULL means the remove have already occurred */
+       if (!ci) {
+-              dout("%s: cap inode is NULL\n", __func__);
++              doutc(cl, "inode is NULL\n");
+               return;
+       }
+       lockdep_assert_held(&ci->i_ceph_lock);
+-      dout("__ceph_remove_cap %p from %p\n", cap, &ci->netfs.inode);
++      doutc(cl, "%p from %p %llx.%llx\n", cap, inode, ceph_vinop(inode));
+       mdsc = ceph_inode_to_fs_client(&ci->netfs.inode)->mdsc;
+@@ -1132,8 +1161,8 @@ void __ceph_remove_cap(struct ceph_cap *
+       spin_lock(&session->s_cap_lock);
+       if (session->s_cap_iterator == cap) {
+               /* not yet, we are iterating over this very cap */
+-              dout("__ceph_remove_cap  delaying %p removal from session %p\n",
+-                   cap, cap->session);
++              doutc(cl, "delaying %p removal from session %p\n", cap,
++                    cap->session);
+       } else {
+               list_del_init(&cap->session_caps);
+               session->s_nr_caps--;
+@@ -1186,7 +1215,7 @@ void ceph_remove_cap(struct ceph_mds_cli
+       /* 'ci' being NULL means the remove have already occurred */
+       if (!ci) {
+-              dout("%s: cap inode is NULL\n", __func__);
++              doutc(mdsc->fsc->client, "inode is NULL\n");
+               return;
+       }
+@@ -1228,15 +1257,19 @@ static void encode_cap_msg(struct ceph_m
+ {
+       struct ceph_mds_caps *fc;
+       void *p;
+-      struct ceph_osd_client *osdc = &arg->session->s_mdsc->fsc->client->osdc;
++      struct ceph_mds_client *mdsc = arg->session->s_mdsc;
++      struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc;
+-      dout("%s %s %llx %llx caps %s wanted %s dirty %s seq %u/%u tid %llu/%llu mseq %u follows %lld size %llu/%llu xattr_ver %llu xattr_len %d\n",
+-           __func__, ceph_cap_op_name(arg->op), arg->cid, arg->ino,
+-           ceph_cap_string(arg->caps), ceph_cap_string(arg->wanted),
+-           ceph_cap_string(arg->dirty), arg->seq, arg->issue_seq,
+-           arg->flush_tid, arg->oldest_flush_tid, arg->mseq, arg->follows,
+-           arg->size, arg->max_size, arg->xattr_version,
+-           arg->xattr_buf ? (int)arg->xattr_buf->vec.iov_len : 0);
++      doutc(mdsc->fsc->client,
++            "%s %llx %llx caps %s wanted %s dirty %s seq %u/%u"
++            " tid %llu/%llu mseq %u follows %lld size %llu/%llu"
++            " xattr_ver %llu xattr_len %d\n",
++            ceph_cap_op_name(arg->op), arg->cid, arg->ino,
++            ceph_cap_string(arg->caps), ceph_cap_string(arg->wanted),
++            ceph_cap_string(arg->dirty), arg->seq, arg->issue_seq,
++            arg->flush_tid, arg->oldest_flush_tid, arg->mseq, arg->follows,
++            arg->size, arg->max_size, arg->xattr_version,
++            arg->xattr_buf ? (int)arg->xattr_buf->vec.iov_len : 0);
+       msg->hdr.version = cpu_to_le16(12);
+       msg->hdr.tid = cpu_to_le64(arg->flush_tid);
+@@ -1373,6 +1406,7 @@ static void __prep_cap(struct cap_msg_ar
+ {
+       struct ceph_inode_info *ci = cap->ci;
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int held, revoking;
+       lockdep_assert_held(&ci->i_ceph_lock);
+@@ -1381,10 +1415,10 @@ static void __prep_cap(struct cap_msg_ar
+       revoking = cap->implemented & ~cap->issued;
+       retain &= ~revoking;
+-      dout("%s %p cap %p session %p %s -> %s (revoking %s)\n",
+-           __func__, inode, cap, cap->session,
+-           ceph_cap_string(held), ceph_cap_string(held & retain),
+-           ceph_cap_string(revoking));
++      doutc(cl, "%p %llx.%llx cap %p session %p %s -> %s (revoking %s)\n",
++            inode, ceph_vinop(inode), cap, cap->session,
++            ceph_cap_string(held), ceph_cap_string(held & retain),
++            ceph_cap_string(revoking));
+       BUG_ON((retain & CEPH_CAP_PIN) == 0);
+       ci->i_ceph_flags &= ~CEPH_I_FLUSH;
+@@ -1500,13 +1534,16 @@ static void __send_cap(struct cap_msg_ar
+ {
+       struct ceph_msg *msg;
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       msg = ceph_msg_new(CEPH_MSG_CLIENT_CAPS, cap_msg_size(arg), GFP_NOFS,
+                          false);
+       if (!msg) {
+-              pr_err("error allocating cap msg: ino (%llx.%llx) flushing %s tid %llu, requeuing cap.\n",
+-                     ceph_vinop(inode), ceph_cap_string(arg->dirty),
+-                     arg->flush_tid);
++              pr_err_client(cl,
++                            "error allocating cap msg: ino (%llx.%llx)"
++                            " flushing %s tid %llu, requeuing cap.\n",
++                            ceph_vinop(inode), ceph_cap_string(arg->dirty),
++                            arg->flush_tid);
+               spin_lock(&ci->i_ceph_lock);
+               __cap_delay_requeue(arg->session->s_mdsc, ci);
+               spin_unlock(&ci->i_ceph_lock);
+@@ -1596,11 +1633,13 @@ static void __ceph_flush_snaps(struct ce
+ {
+       struct inode *inode = &ci->netfs.inode;
+       struct ceph_mds_client *mdsc = session->s_mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_cap_snap *capsnap;
+       u64 oldest_flush_tid = 0;
+       u64 first_tid = 1, last_tid = 0;
+-      dout("__flush_snaps %p session %p\n", inode, session);
++      doutc(cl, "%p %llx.%llx session %p\n", inode, ceph_vinop(inode),
++            session);
+       list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) {
+               /*
+@@ -1615,7 +1654,7 @@ static void __ceph_flush_snaps(struct ce
+               /* only flush each capsnap once */
+               if (capsnap->cap_flush.tid > 0) {
+-                      dout(" already flushed %p, skipping\n", capsnap);
++                      doutc(cl, "already flushed %p, skipping\n", capsnap);
+                       continue;
+               }
+@@ -1647,8 +1686,8 @@ static void __ceph_flush_snaps(struct ce
+               int ret;
+               if (!(cap && cap->session == session)) {
+-                      dout("__flush_snaps %p auth cap %p not mds%d, "
+-                           "stop\n", inode, cap, session->s_mds);
++                      doutc(cl, "%p %llx.%llx auth cap %p not mds%d, stop\n",
++                            inode, ceph_vinop(inode), cap, session->s_mds);
+                       break;
+               }
+@@ -1669,15 +1708,17 @@ static void __ceph_flush_snaps(struct ce
+               refcount_inc(&capsnap->nref);
+               spin_unlock(&ci->i_ceph_lock);
+-              dout("__flush_snaps %p capsnap %p tid %llu %s\n",
+-                   inode, capsnap, cf->tid, ceph_cap_string(capsnap->dirty));
++              doutc(cl, "%p %llx.%llx capsnap %p tid %llu %s\n", inode,
++                    ceph_vinop(inode), capsnap, cf->tid,
++                    ceph_cap_string(capsnap->dirty));
+               ret = __send_flush_snap(inode, session, capsnap, cap->mseq,
+                                       oldest_flush_tid);
+               if (ret < 0) {
+-                      pr_err("__flush_snaps: error sending cap flushsnap, "
+-                             "ino (%llx.%llx) tid %llu follows %llu\n",
+-                              ceph_vinop(inode), cf->tid, capsnap->follows);
++                      pr_err_client(cl, "error sending cap flushsnap, "
++                                    "ino (%llx.%llx) tid %llu follows %llu\n",
++                                    ceph_vinop(inode), cf->tid,
++                                    capsnap->follows);
+               }
+               ceph_put_cap_snap(capsnap);
+@@ -1690,27 +1731,28 @@ void ceph_flush_snaps(struct ceph_inode_
+ {
+       struct inode *inode = &ci->netfs.inode;
+       struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_mds_session *session = NULL;
+       bool need_put = false;
+       int mds;
+-      dout("ceph_flush_snaps %p\n", inode);
++      doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
+       if (psession)
+               session = *psession;
+ retry:
+       spin_lock(&ci->i_ceph_lock);
+       if (!(ci->i_ceph_flags & CEPH_I_FLUSH_SNAPS)) {
+-              dout(" no capsnap needs flush, doing nothing\n");
++              doutc(cl, " no capsnap needs flush, doing nothing\n");
+               goto out;
+       }
+       if (!ci->i_auth_cap) {
+-              dout(" no auth cap (migrating?), doing nothing\n");
++              doutc(cl, " no auth cap (migrating?), doing nothing\n");
+               goto out;
+       }
+       mds = ci->i_auth_cap->session->s_mds;
+       if (session && session->s_mds != mds) {
+-              dout(" oops, wrong session %p mutex\n", session);
++              doutc(cl, " oops, wrong session %p mutex\n", session);
+               ceph_put_mds_session(session);
+               session = NULL;
+       }
+@@ -1756,21 +1798,23 @@ int __ceph_mark_dirty_caps(struct ceph_i
+       struct ceph_mds_client *mdsc =
+               ceph_sb_to_fs_client(ci->netfs.inode.i_sb)->mdsc;
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int was = ci->i_dirty_caps;
+       int dirty = 0;
+       lockdep_assert_held(&ci->i_ceph_lock);
+       if (!ci->i_auth_cap) {
+-              pr_warn("__mark_dirty_caps %p %llx mask %s, "
+-                      "but no auth cap (session was closed?)\n",
+-                      inode, ceph_ino(inode), ceph_cap_string(mask));
++              pr_warn_client(cl, "%p %llx.%llx mask %s, "
++                             "but no auth cap (session was closed?)\n",
++                              inode, ceph_vinop(inode),
++                              ceph_cap_string(mask));
+               return 0;
+       }
+-      dout("__mark_dirty_caps %p %s dirty %s -> %s\n", &ci->netfs.inode,
+-           ceph_cap_string(mask), ceph_cap_string(was),
+-           ceph_cap_string(was | mask));
++      doutc(cl, "%p %llx.%llx %s dirty %s -> %s\n", inode,
++            ceph_vinop(inode), ceph_cap_string(mask),
++            ceph_cap_string(was), ceph_cap_string(was | mask));
+       ci->i_dirty_caps |= mask;
+       if (was == 0) {
+               struct ceph_mds_session *session = ci->i_auth_cap->session;
+@@ -1783,8 +1827,9 @@ int __ceph_mark_dirty_caps(struct ceph_i
+                       ci->i_head_snapc = ceph_get_snap_context(
+                               ci->i_snap_realm->cached_context);
+               }
+-              dout(" inode %p now dirty snapc %p auth cap %p\n",
+-                   &ci->netfs.inode, ci->i_head_snapc, ci->i_auth_cap);
++              doutc(cl, "%p %llx.%llx now dirty snapc %p auth cap %p\n",
++                    inode, ceph_vinop(inode), ci->i_head_snapc,
++                    ci->i_auth_cap);
+               BUG_ON(!list_empty(&ci->i_dirty_item));
+               spin_lock(&mdsc->cap_dirty_lock);
+               list_add(&ci->i_dirty_item, &session->s_cap_dirty);
+@@ -1878,6 +1923,7 @@ static u64 __mark_caps_flushing(struct i
+                               u64 *oldest_flush_tid)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_cap_flush *cf = NULL;
+       int flushing;
+@@ -1888,13 +1934,13 @@ static u64 __mark_caps_flushing(struct i
+       BUG_ON(!ci->i_prealloc_cap_flush);
+       flushing = ci->i_dirty_caps;
+-      dout("__mark_caps_flushing flushing %s, flushing_caps %s -> %s\n",
+-           ceph_cap_string(flushing),
+-           ceph_cap_string(ci->i_flushing_caps),
+-           ceph_cap_string(ci->i_flushing_caps | flushing));
++      doutc(cl, "flushing %s, flushing_caps %s -> %s\n",
++            ceph_cap_string(flushing),
++            ceph_cap_string(ci->i_flushing_caps),
++            ceph_cap_string(ci->i_flushing_caps | flushing));
+       ci->i_flushing_caps |= flushing;
+       ci->i_dirty_caps = 0;
+-      dout(" inode %p now !dirty\n", inode);
++      doutc(cl, "%p %llx.%llx now !dirty\n", inode, ceph_vinop(inode));
+       swap(cf, ci->i_prealloc_cap_flush);
+       cf->caps = flushing;
+@@ -1925,6 +1971,7 @@ static int try_nonblocking_invalidate(st
+       __releases(ci->i_ceph_lock)
+       __acquires(ci->i_ceph_lock)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       u32 invalidating_gen = ci->i_rdcache_gen;
+@@ -1936,12 +1983,13 @@ static int try_nonblocking_invalidate(st
+       if (inode->i_data.nrpages == 0 &&
+           invalidating_gen == ci->i_rdcache_gen) {
+               /* success. */
+-              dout("try_nonblocking_invalidate %p success\n", inode);
++              doutc(cl, "%p %llx.%llx success\n", inode,
++                    ceph_vinop(inode));
+               /* save any racing async invalidate some trouble */
+               ci->i_rdcache_revoking = ci->i_rdcache_gen - 1;
+               return 0;
+       }
+-      dout("try_nonblocking_invalidate %p failed\n", inode);
++      doutc(cl, "%p %llx.%llx failed\n", inode, ceph_vinop(inode));
+       return -1;
+ }
+@@ -1973,6 +2021,7 @@ void ceph_check_caps(struct ceph_inode_i
+ {
+       struct inode *inode = &ci->netfs.inode;
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_cap *cap;
+       u64 flush_tid, oldest_flush_tid;
+       int file_wanted, used, cap_used;
+@@ -2047,9 +2096,9 @@ retry:
+               }
+       }
+-      dout("check_caps %llx.%llx file_want %s used %s dirty %s flushing %s"
+-           " issued %s revoking %s retain %s %s%s%s\n", ceph_vinop(inode),
+-           ceph_cap_string(file_wanted),
++      doutc(cl, "%p %llx.%llx file_want %s used %s dirty %s "
++            "flushing %s issued %s revoking %s retain %s %s%s%s\n",
++           inode, ceph_vinop(inode), ceph_cap_string(file_wanted),
+            ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps),
+            ceph_cap_string(ci->i_flushing_caps),
+            ceph_cap_string(issued), ceph_cap_string(revoking),
+@@ -2070,10 +2119,10 @@ retry:
+           (revoking & (CEPH_CAP_FILE_CACHE|
+                        CEPH_CAP_FILE_LAZYIO)) && /*  or revoking cache */
+           !tried_invalidate) {
+-              dout("check_caps trying to invalidate on %llx.%llx\n",
+-                   ceph_vinop(inode));
++              doutc(cl, "trying to invalidate on %p %llx.%llx\n",
++                    inode, ceph_vinop(inode));
+               if (try_nonblocking_invalidate(inode) < 0) {
+-                      dout("check_caps queuing invalidate\n");
++                      doutc(cl, "queuing invalidate\n");
+                       queue_invalidate = true;
+                       ci->i_rdcache_revoking = ci->i_rdcache_gen;
+               }
+@@ -2101,35 +2150,35 @@ retry:
+                       cap_used &= ~ci->i_auth_cap->issued;
+               revoking = cap->implemented & ~cap->issued;
+-              dout(" mds%d cap %p used %s issued %s implemented %s revoking %s\n",
+-                   cap->mds, cap, ceph_cap_string(cap_used),
+-                   ceph_cap_string(cap->issued),
+-                   ceph_cap_string(cap->implemented),
+-                   ceph_cap_string(revoking));
++              doutc(cl, " mds%d cap %p used %s issued %s implemented %s revoking %s\n",
++                    cap->mds, cap, ceph_cap_string(cap_used),
++                    ceph_cap_string(cap->issued),
++                    ceph_cap_string(cap->implemented),
++                    ceph_cap_string(revoking));
+               if (cap == ci->i_auth_cap &&
+                   (cap->issued & CEPH_CAP_FILE_WR)) {
+                       /* request larger max_size from MDS? */
+                       if (ci->i_wanted_max_size > ci->i_max_size &&
+                           ci->i_wanted_max_size > ci->i_requested_max_size) {
+-                              dout("requesting new max_size\n");
++                              doutc(cl, "requesting new max_size\n");
+                               goto ack;
+                       }
+                       /* approaching file_max? */
+                       if (__ceph_should_report_size(ci)) {
+-                              dout("i_size approaching max_size\n");
++                              doutc(cl, "i_size approaching max_size\n");
+                               goto ack;
+                       }
+               }
+               /* flush anything dirty? */
+               if (cap == ci->i_auth_cap) {
+                       if ((flags & CHECK_CAPS_FLUSH) && ci->i_dirty_caps) {
+-                              dout("flushing dirty caps\n");
++                              doutc(cl, "flushing dirty caps\n");
+                               goto ack;
+                       }
+                       if (ci->i_ceph_flags & CEPH_I_FLUSH_SNAPS) {
+-                              dout("flushing snap caps\n");
++                              doutc(cl, "flushing snap caps\n");
+                               goto ack;
+                       }
+               }
+@@ -2137,7 +2186,7 @@ retry:
+               /* completed revocation? going down and there are no caps? */
+               if (revoking) {
+                       if ((revoking & cap_used) == 0) {
+-                              dout("completed revocation of %s\n",
++                              doutc(cl, "completed revocation of %s\n",
+                                     ceph_cap_string(cap->implemented & ~cap->issued));
+                               goto ack;
+                       }
+@@ -2315,6 +2364,7 @@ static int caps_are_flushed(struct inode
+ static int flush_mdlog_and_wait_inode_unsafe_requests(struct inode *inode)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_request *req1 = NULL, *req2 = NULL;
+       int ret, err = 0;
+@@ -2404,8 +2454,9 @@ static int flush_mdlog_and_wait_inode_un
+               kfree(sessions);
+       }
+-      dout("%s %p wait on tid %llu %llu\n", __func__,
+-           inode, req1 ? req1->r_tid : 0ULL, req2 ? req2->r_tid : 0ULL);
++      doutc(cl, "%p %llx.%llx wait on tid %llu %llu\n", inode,
++            ceph_vinop(inode), req1 ? req1->r_tid : 0ULL,
++            req2 ? req2->r_tid : 0ULL);
+       if (req1) {
+               ret = !wait_for_completion_timeout(&req1->r_safe_completion,
+                                       ceph_timeout_jiffies(req1->r_timeout));
+@@ -2431,11 +2482,13 @@ int ceph_fsync(struct file *file, loff_t
+ {
+       struct inode *inode = file->f_mapping->host;
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       u64 flush_tid;
+       int ret, err;
+       int dirty;
+-      dout("fsync %p%s\n", inode, datasync ? " datasync" : "");
++      doutc(cl, "%p %llx.%llx%s\n", inode, ceph_vinop(inode),
++            datasync ? " datasync" : "");
+       ret = file_write_and_wait_range(file, start, end);
+       if (datasync)
+@@ -2446,7 +2499,7 @@ int ceph_fsync(struct file *file, loff_t
+               goto out;
+       dirty = try_flush_caps(inode, &flush_tid);
+-      dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
++      doutc(cl, "dirty caps are %s\n", ceph_cap_string(dirty));
+       err = flush_mdlog_and_wait_inode_unsafe_requests(inode);
+@@ -2467,7 +2520,8 @@ int ceph_fsync(struct file *file, loff_t
+       if (err < 0)
+               ret = err;
+ out:
+-      dout("fsync %p%s result=%d\n", inode, datasync ? " datasync" : "", ret);
++      doutc(cl, "%p %llx.%llx%s result=%d\n", inode, ceph_vinop(inode),
++            datasync ? " datasync" : "", ret);
+       return ret;
+ }
+@@ -2480,12 +2534,13 @@ out:
+ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       u64 flush_tid;
+       int err = 0;
+       int dirty;
+       int wait = (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync);
+-      dout("write_inode %p wait=%d\n", inode, wait);
++      doutc(cl, "%p %llx.%llx wait=%d\n", inode, ceph_vinop(inode), wait);
+       ceph_fscache_unpin_writeback(inode, wbc);
+       if (wait) {
+               err = ceph_wait_on_async_create(inode);
+@@ -2515,6 +2570,7 @@ static void __kick_flushing_caps(struct
+       __acquires(ci->i_ceph_lock)
+ {
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_cap *cap;
+       struct ceph_cap_flush *cf;
+       int ret;
+@@ -2540,8 +2596,8 @@ static void __kick_flushing_caps(struct
+               cap = ci->i_auth_cap;
+               if (!(cap && cap->session == session)) {
+-                      pr_err("%p auth cap %p not mds%d ???\n",
+-                             inode, cap, session->s_mds);
++                      pr_err_client(cl, "%p auth cap %p not mds%d ???\n",
++                                    inode, cap, session->s_mds);
+                       break;
+               }
+@@ -2550,8 +2606,9 @@ static void __kick_flushing_caps(struct
+               if (!cf->is_capsnap) {
+                       struct cap_msg_args arg;
+-                      dout("kick_flushing_caps %p cap %p tid %llu %s\n",
+-                           inode, cap, cf->tid, ceph_cap_string(cf->caps));
++                      doutc(cl, "%p %llx.%llx cap %p tid %llu %s\n",
++                            inode, ceph_vinop(inode), cap, cf->tid,
++                            ceph_cap_string(cf->caps));
+                       __prep_cap(&arg, cap, CEPH_CAP_OP_FLUSH,
+                                        (cf->tid < last_snap_flush ?
+                                         CEPH_CLIENT_CAPS_PENDING_CAPSNAP : 0),
+@@ -2565,9 +2622,9 @@ static void __kick_flushing_caps(struct
+                       struct ceph_cap_snap *capsnap =
+                                       container_of(cf, struct ceph_cap_snap,
+                                                   cap_flush);
+-                      dout("kick_flushing_caps %p capsnap %p tid %llu %s\n",
+-                           inode, capsnap, cf->tid,
+-                           ceph_cap_string(capsnap->dirty));
++                      doutc(cl, "%p %llx.%llx capsnap %p tid %llu %s\n",
++                            inode, ceph_vinop(inode), capsnap, cf->tid,
++                            ceph_cap_string(capsnap->dirty));
+                       refcount_inc(&capsnap->nref);
+                       spin_unlock(&ci->i_ceph_lock);
+@@ -2575,11 +2632,10 @@ static void __kick_flushing_caps(struct
+                       ret = __send_flush_snap(inode, session, capsnap, cap->mseq,
+                                               oldest_flush_tid);
+                       if (ret < 0) {
+-                              pr_err("kick_flushing_caps: error sending "
+-                                      "cap flushsnap, ino (%llx.%llx) "
+-                                      "tid %llu follows %llu\n",
+-                                      ceph_vinop(inode), cf->tid,
+-                                      capsnap->follows);
++                              pr_err_client(cl, "error sending cap flushsnap,"
++                                            " %p %llx.%llx tid %llu follows %llu\n",
++                                            inode, ceph_vinop(inode), cf->tid,
++                                            capsnap->follows);
+                       }
+                       ceph_put_cap_snap(capsnap);
+@@ -2592,22 +2648,26 @@ static void __kick_flushing_caps(struct
+ void ceph_early_kick_flushing_caps(struct ceph_mds_client *mdsc,
+                                  struct ceph_mds_session *session)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *ci;
+       struct ceph_cap *cap;
+       u64 oldest_flush_tid;
+-      dout("early_kick_flushing_caps mds%d\n", session->s_mds);
++      doutc(cl, "mds%d\n", session->s_mds);
+       spin_lock(&mdsc->cap_dirty_lock);
+       oldest_flush_tid = __get_oldest_flush_tid(mdsc);
+       spin_unlock(&mdsc->cap_dirty_lock);
+       list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
++              struct inode *inode = &ci->netfs.inode;
++
+               spin_lock(&ci->i_ceph_lock);
+               cap = ci->i_auth_cap;
+               if (!(cap && cap->session == session)) {
+-                      pr_err("%p auth cap %p not mds%d ???\n",
+-                              &ci->netfs.inode, cap, session->s_mds);
++                      pr_err_client(cl, "%p %llx.%llx auth cap %p not mds%d ???\n",
++                                    inode, ceph_vinop(inode), cap,
++                                    session->s_mds);
+                       spin_unlock(&ci->i_ceph_lock);
+                       continue;
+               }
+@@ -2640,24 +2700,28 @@ void ceph_early_kick_flushing_caps(struc
+ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
+                            struct ceph_mds_session *session)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *ci;
+       struct ceph_cap *cap;
+       u64 oldest_flush_tid;
+       lockdep_assert_held(&session->s_mutex);
+-      dout("kick_flushing_caps mds%d\n", session->s_mds);
++      doutc(cl, "mds%d\n", session->s_mds);
+       spin_lock(&mdsc->cap_dirty_lock);
+       oldest_flush_tid = __get_oldest_flush_tid(mdsc);
+       spin_unlock(&mdsc->cap_dirty_lock);
+       list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
++              struct inode *inode = &ci->netfs.inode;
++
+               spin_lock(&ci->i_ceph_lock);
+               cap = ci->i_auth_cap;
+               if (!(cap && cap->session == session)) {
+-                      pr_err("%p auth cap %p not mds%d ???\n",
+-                              &ci->netfs.inode, cap, session->s_mds);
++                      pr_err_client(cl, "%p %llx.%llx auth cap %p not mds%d ???\n",
++                                    inode, ceph_vinop(inode), cap,
++                                    session->s_mds);
+                       spin_unlock(&ci->i_ceph_lock);
+                       continue;
+               }
+@@ -2674,11 +2738,13 @@ void ceph_kick_flushing_inode_caps(struc
+ {
+       struct ceph_mds_client *mdsc = session->s_mdsc;
+       struct ceph_cap *cap = ci->i_auth_cap;
++      struct inode *inode = &ci->netfs.inode;
+       lockdep_assert_held(&ci->i_ceph_lock);
+-      dout("%s %p flushing %s\n", __func__, &ci->netfs.inode,
+-           ceph_cap_string(ci->i_flushing_caps));
++      doutc(mdsc->fsc->client, "%p %llx.%llx flushing %s\n",
++            inode, ceph_vinop(inode),
++            ceph_cap_string(ci->i_flushing_caps));
+       if (!list_empty(&ci->i_cap_flush_list)) {
+               u64 oldest_flush_tid;
+@@ -2700,6 +2766,9 @@ void ceph_kick_flushing_inode_caps(struc
+ void ceph_take_cap_refs(struct ceph_inode_info *ci, int got,
+                           bool snap_rwsem_locked)
+ {
++      struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
++
+       lockdep_assert_held(&ci->i_ceph_lock);
+       if (got & CEPH_CAP_PIN)
+@@ -2720,10 +2789,10 @@ void ceph_take_cap_refs(struct ceph_inod
+       }
+       if (got & CEPH_CAP_FILE_BUFFER) {
+               if (ci->i_wb_ref == 0)
+-                      ihold(&ci->netfs.inode);
++                      ihold(inode);
+               ci->i_wb_ref++;
+-              dout("%s %p wb %d -> %d (?)\n", __func__,
+-                   &ci->netfs.inode, ci->i_wb_ref-1, ci->i_wb_ref);
++              doutc(cl, "%p %llx.%llx wb %d -> %d (?)\n", inode,
++                    ceph_vinop(inode), ci->i_wb_ref-1, ci->i_wb_ref);
+       }
+ }
+@@ -2751,19 +2820,22 @@ static int try_get_cap_refs(struct inode
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int ret = 0;
+       int have, implemented;
+       bool snap_rwsem_locked = false;
+-      dout("get_cap_refs %p need %s want %s\n", inode,
+-           ceph_cap_string(need), ceph_cap_string(want));
++      doutc(cl, "%p %llx.%llx need %s want %s\n", inode,
++            ceph_vinop(inode), ceph_cap_string(need),
++            ceph_cap_string(want));
+ again:
+       spin_lock(&ci->i_ceph_lock);
+       if ((flags & CHECK_FILELOCK) &&
+           (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK)) {
+-              dout("try_get_cap_refs %p error filelock\n", inode);
++              doutc(cl, "%p %llx.%llx error filelock\n", inode,
++                    ceph_vinop(inode));
+               ret = -EIO;
+               goto out_unlock;
+       }
+@@ -2783,8 +2855,8 @@ again:
+       if (have & need & CEPH_CAP_FILE_WR) {
+               if (endoff >= 0 && endoff > (loff_t)ci->i_max_size) {
+-                      dout("get_cap_refs %p endoff %llu > maxsize %llu\n",
+-                           inode, endoff, ci->i_max_size);
++                      doutc(cl, "%p %llx.%llx endoff %llu > maxsize %llu\n",
++                            inode, ceph_vinop(inode), endoff, ci->i_max_size);
+                       if (endoff > ci->i_requested_max_size)
+                               ret = ci->i_auth_cap ? -EFBIG : -EUCLEAN;
+                       goto out_unlock;
+@@ -2794,7 +2866,8 @@ again:
+                * can get a final snapshot value for size+mtime.
+                */
+               if (__ceph_have_pending_cap_snap(ci)) {
+-                      dout("get_cap_refs %p cap_snap_pending\n", inode);
++                      doutc(cl, "%p %llx.%llx cap_snap_pending\n", inode,
++                            ceph_vinop(inode));
+                       goto out_unlock;
+               }
+       }
+@@ -2812,9 +2885,9 @@ again:
+               int not = want & ~(have & need);
+               int revoking = implemented & ~have;
+               int exclude = revoking & not;
+-              dout("get_cap_refs %p have %s but not %s (revoking %s)\n",
+-                   inode, ceph_cap_string(have), ceph_cap_string(not),
+-                   ceph_cap_string(revoking));
++              doutc(cl, "%p %llx.%llx have %s but not %s (revoking %s)\n",
++                    inode, ceph_vinop(inode), ceph_cap_string(have),
++                    ceph_cap_string(not), ceph_cap_string(revoking));
+               if (!exclude || !(exclude & CEPH_CAP_FILE_BUFFER)) {
+                       if (!snap_rwsem_locked &&
+                           !ci->i_head_snapc &&
+@@ -2854,28 +2927,31 @@ again:
+                       spin_unlock(&s->s_cap_lock);
+               }
+               if (session_readonly) {
+-                      dout("get_cap_refs %p need %s but mds%d readonly\n",
+-                           inode, ceph_cap_string(need), ci->i_auth_cap->mds);
++                      doutc(cl, "%p %llx.%llx need %s but mds%d readonly\n",
++                            inode, ceph_vinop(inode), ceph_cap_string(need),
++                            ci->i_auth_cap->mds);
+                       ret = -EROFS;
+                       goto out_unlock;
+               }
+               if (ceph_inode_is_shutdown(inode)) {
+-                      dout("get_cap_refs %p inode is shutdown\n", inode);
++                      doutc(cl, "%p %llx.%llx inode is shutdown\n",
++                            inode, ceph_vinop(inode));
+                       ret = -ESTALE;
+                       goto out_unlock;
+               }
+               mds_wanted = __ceph_caps_mds_wanted(ci, false);
+               if (need & ~mds_wanted) {
+-                      dout("get_cap_refs %p need %s > mds_wanted %s\n",
+-                           inode, ceph_cap_string(need),
+-                           ceph_cap_string(mds_wanted));
++                      doutc(cl, "%p %llx.%llx need %s > mds_wanted %s\n",
++                            inode, ceph_vinop(inode), ceph_cap_string(need),
++                            ceph_cap_string(mds_wanted));
+                       ret = -EUCLEAN;
+                       goto out_unlock;
+               }
+-              dout("get_cap_refs %p have %s need %s\n", inode,
+-                   ceph_cap_string(have), ceph_cap_string(need));
++              doutc(cl, "%p %llx.%llx have %s need %s\n", inode,
++                    ceph_vinop(inode), ceph_cap_string(have),
++                    ceph_cap_string(need));
+       }
+ out_unlock:
+@@ -2890,8 +2966,8 @@ out_unlock:
+       else if (ret == 1)
+               ceph_update_cap_hit(&mdsc->metric);
+-      dout("get_cap_refs %p ret %d got %s\n", inode,
+-           ret, ceph_cap_string(*got));
++      doutc(cl, "%p %llx.%llx ret %d got %s\n", inode,
++            ceph_vinop(inode), ret, ceph_cap_string(*got));
+       return ret;
+ }
+@@ -2903,13 +2979,14 @@ out_unlock:
+ static void check_max_size(struct inode *inode, loff_t endoff)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int check = 0;
+       /* do we need to explicitly request a larger max_size? */
+       spin_lock(&ci->i_ceph_lock);
+       if (endoff >= ci->i_max_size && endoff > ci->i_wanted_max_size) {
+-              dout("write %p at large endoff %llu, req max_size\n",
+-                   inode, endoff);
++              doutc(cl, "write %p %llx.%llx at large endoff %llu, req max_size\n",
++                    inode, ceph_vinop(inode), endoff);
+               ci->i_wanted_max_size = endoff;
+       }
+       /* duplicate ceph_check_caps()'s logic */
+@@ -3119,10 +3196,12 @@ void ceph_get_cap_refs(struct ceph_inode
+ static int ceph_try_drop_cap_snap(struct ceph_inode_info *ci,
+                                 struct ceph_cap_snap *capsnap)
+ {
++      struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
++
+       if (!capsnap->need_flush &&
+           !capsnap->writing && !capsnap->dirty_pages) {
+-              dout("dropping cap_snap %p follows %llu\n",
+-                   capsnap, capsnap->follows);
++              doutc(cl, "%p follows %llu\n", capsnap, capsnap->follows);
+               BUG_ON(capsnap->cap_flush.tid > 0);
+               ceph_put_snap_context(capsnap->context);
+               if (!list_is_last(&capsnap->ci_item, &ci->i_cap_snaps))
+@@ -3154,6 +3233,7 @@ static void __ceph_put_cap_refs(struct c
+                               enum put_cap_refs_mode mode)
+ {
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int last = 0, put = 0, flushsnaps = 0, wake = 0;
+       bool check_flushsnaps = false;
+@@ -3176,8 +3256,8 @@ static void __ceph_put_cap_refs(struct c
+                       put++;
+                       check_flushsnaps = true;
+               }
+-              dout("put_cap_refs %p wb %d -> %d (?)\n",
+-                   inode, ci->i_wb_ref+1, ci->i_wb_ref);
++              doutc(cl, "%p %llx.%llx wb %d -> %d (?)\n", inode,
++                    ceph_vinop(inode), ci->i_wb_ref+1, ci->i_wb_ref);
+       }
+       if (had & CEPH_CAP_FILE_WR) {
+               if (--ci->i_wr_ref == 0) {
+@@ -3217,8 +3297,8 @@ static void __ceph_put_cap_refs(struct c
+       }
+       spin_unlock(&ci->i_ceph_lock);
+-      dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had),
+-           last ? " last" : "", put ? " put" : "");
++      doutc(cl, "%p %llx.%llx had %s%s%s\n", inode, ceph_vinop(inode),
++            ceph_cap_string(had), last ? " last" : "", put ? " put" : "");
+       switch (mode) {
+       case PUT_CAP_REFS_SYNC:
+@@ -3268,6 +3348,7 @@ void ceph_put_wrbuffer_cap_refs(struct c
+                               struct ceph_snap_context *snapc)
+ {
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_cap_snap *capsnap = NULL, *iter;
+       int put = 0;
+       bool last = false;
+@@ -3291,11 +3372,10 @@ void ceph_put_wrbuffer_cap_refs(struct c
+                       ceph_put_snap_context(ci->i_head_snapc);
+                       ci->i_head_snapc = NULL;
+               }
+-              dout("put_wrbuffer_cap_refs on %p head %d/%d -> %d/%d %s\n",
+-                   inode,
+-                   ci->i_wrbuffer_ref+nr, ci->i_wrbuffer_ref_head+nr,
+-                   ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head,
+-                   last ? " LAST" : "");
++              doutc(cl, "on %p %llx.%llx head %d/%d -> %d/%d %s\n",
++                    inode, ceph_vinop(inode), ci->i_wrbuffer_ref+nr,
++                    ci->i_wrbuffer_ref_head+nr, ci->i_wrbuffer_ref,
++                    ci->i_wrbuffer_ref_head, last ? " LAST" : "");
+       } else {
+               list_for_each_entry(iter, &ci->i_cap_snaps, ci_item) {
+                       if (iter->context == snapc) {
+@@ -3325,13 +3405,12 @@ void ceph_put_wrbuffer_cap_refs(struct c
+                               }
+                       }
+               }
+-              dout("put_wrbuffer_cap_refs on %p cap_snap %p "
+-                   " snap %lld %d/%d -> %d/%d %s%s\n",
+-                   inode, capsnap, capsnap->context->seq,
+-                   ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr,
+-                   ci->i_wrbuffer_ref, capsnap->dirty_pages,
+-                   last ? " (wrbuffer last)" : "",
+-                   complete_capsnap ? " (complete capsnap)" : "");
++              doutc(cl, "%p %llx.%llx cap_snap %p snap %lld %d/%d -> %d/%d %s%s\n",
++                    inode, ceph_vinop(inode), capsnap, capsnap->context->seq,
++                    ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr,
++                    ci->i_wrbuffer_ref, capsnap->dirty_pages,
++                    last ? " (wrbuffer last)" : "",
++                    complete_capsnap ? " (complete capsnap)" : "");
+       }
+ unlock:
+@@ -3354,9 +3433,10 @@ unlock:
+  */
+ static void invalidate_aliases(struct inode *inode)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct dentry *dn, *prev = NULL;
+-      dout("invalidate_aliases inode %p\n", inode);
++      doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
+       d_prune_aliases(inode);
+       /*
+        * For non-directory inode, d_find_alias() only returns
+@@ -3415,6 +3495,7 @@ static void handle_cap_grant(struct inod
+       __releases(ci->i_ceph_lock)
+       __releases(session->s_mdsc->snap_rwsem)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       int seq = le32_to_cpu(grant->seq);
+       int newcaps = le32_to_cpu(grant->caps);
+@@ -3438,10 +3519,11 @@ static void handle_cap_grant(struct inod
+       if (IS_ENCRYPTED(inode) && size)
+               size = extra_info->fscrypt_file_size;
+-      dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
+-           inode, cap, session->s_mds, seq, ceph_cap_string(newcaps));
+-      dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
+-              i_size_read(inode));
++      doutc(cl, "%p %llx.%llx cap %p mds%d seq %d %s\n", inode,
++            ceph_vinop(inode), cap, session->s_mds, seq,
++            ceph_cap_string(newcaps));
++      doutc(cl, " size %llu max_size %llu, i_size %llu\n", size,
++            max_size, i_size_read(inode));
+       /*
+@@ -3501,15 +3583,17 @@ static void handle_cap_grant(struct inod
+               inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
+               inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
+               ci->i_btime = extra_info->btime;
+-              dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
+-                   from_kuid(&init_user_ns, inode->i_uid),
+-                   from_kgid(&init_user_ns, inode->i_gid));
++              doutc(cl, "%p %llx.%llx mode 0%o uid.gid %d.%d\n", inode,
++                    ceph_vinop(inode), inode->i_mode,
++                    from_kuid(&init_user_ns, inode->i_uid),
++                    from_kgid(&init_user_ns, inode->i_gid));
+ #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
+               if (ci->fscrypt_auth_len != extra_info->fscrypt_auth_len ||
+                   memcmp(ci->fscrypt_auth, extra_info->fscrypt_auth,
+                          ci->fscrypt_auth_len))
+-                      pr_warn_ratelimited("%s: cap grant attempt to change fscrypt_auth on non-I_NEW inode (old len %d new len %d)\n",
+-                              __func__, ci->fscrypt_auth_len,
++                      pr_warn_ratelimited_client(cl,
++                              "cap grant attempt to change fscrypt_auth on non-I_NEW inode (old len %d new len %d)\n",
++                              ci->fscrypt_auth_len,
+                               extra_info->fscrypt_auth_len);
+ #endif
+       }
+@@ -3527,8 +3611,8 @@ static void handle_cap_grant(struct inod
+               u64 version = le64_to_cpu(grant->xattr_version);
+               if (version > ci->i_xattrs.version) {
+-                      dout(" got new xattrs v%llu on %p len %d\n",
+-                           version, inode, len);
++                      doutc(cl, " got new xattrs v%llu on %p %llx.%llx len %d\n",
++                            version, inode, ceph_vinop(inode), len);
+                       if (ci->i_xattrs.blob)
+                               ceph_buffer_put(ci->i_xattrs.blob);
+                       ci->i_xattrs.blob = ceph_buffer_get(xattr_buf);
+@@ -3579,8 +3663,8 @@ static void handle_cap_grant(struct inod
+       if (ci->i_auth_cap == cap && (newcaps & CEPH_CAP_ANY_FILE_WR)) {
+               if (max_size != ci->i_max_size) {
+-                      dout("max_size %lld -> %llu\n",
+-                           ci->i_max_size, max_size);
++                      doutc(cl, "max_size %lld -> %llu\n", ci->i_max_size,
++                            max_size);
+                       ci->i_max_size = max_size;
+                       if (max_size >= ci->i_wanted_max_size) {
+                               ci->i_wanted_max_size = 0;  /* reset */
+@@ -3594,10 +3678,9 @@ static void handle_cap_grant(struct inod
+       wanted = __ceph_caps_wanted(ci);
+       used = __ceph_caps_used(ci);
+       dirty = __ceph_caps_dirty(ci);
+-      dout(" my wanted = %s, used = %s, dirty %s\n",
+-           ceph_cap_string(wanted),
+-           ceph_cap_string(used),
+-           ceph_cap_string(dirty));
++      doutc(cl, " my wanted = %s, used = %s, dirty %s\n",
++            ceph_cap_string(wanted), ceph_cap_string(used),
++            ceph_cap_string(dirty));
+       if ((was_stale || le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) &&
+           (wanted & ~(cap->mds_wanted | newcaps))) {
+@@ -3618,10 +3701,9 @@ static void handle_cap_grant(struct inod
+       if (cap->issued & ~newcaps) {
+               int revoking = cap->issued & ~newcaps;
+-              dout("revocation: %s -> %s (revoking %s)\n",
+-                   ceph_cap_string(cap->issued),
+-                   ceph_cap_string(newcaps),
+-                   ceph_cap_string(revoking));
++              doutc(cl, "revocation: %s -> %s (revoking %s)\n",
++                    ceph_cap_string(cap->issued), ceph_cap_string(newcaps),
++                    ceph_cap_string(revoking));
+               if (S_ISREG(inode->i_mode) &&
+                   (revoking & used & CEPH_CAP_FILE_BUFFER))
+                       writeback = true;  /* initiate writeback; will delay ack */
+@@ -3639,11 +3721,12 @@ static void handle_cap_grant(struct inod
+               cap->issued = newcaps;
+               cap->implemented |= newcaps;
+       } else if (cap->issued == newcaps) {
+-              dout("caps unchanged: %s -> %s\n",
+-                   ceph_cap_string(cap->issued), ceph_cap_string(newcaps));
++              doutc(cl, "caps unchanged: %s -> %s\n",
++                    ceph_cap_string(cap->issued),
++                    ceph_cap_string(newcaps));
+       } else {
+-              dout("grant: %s -> %s\n", ceph_cap_string(cap->issued),
+-                   ceph_cap_string(newcaps));
++              doutc(cl, "grant: %s -> %s\n", ceph_cap_string(cap->issued),
++                    ceph_cap_string(newcaps));
+               /* non-auth MDS is revoking the newly grant caps ? */
+               if (cap == ci->i_auth_cap &&
+                   __ceph_caps_revoking_other(ci, cap, newcaps))
+@@ -3732,6 +3815,7 @@ static void handle_cap_flush_ack(struct
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_cap_flush *cf, *tmp_cf;
+       LIST_HEAD(to_remove);
+       unsigned seq = le32_to_cpu(m->seq);
+@@ -3768,11 +3852,11 @@ static void handle_cap_flush_ack(struct
+               }
+       }
+-      dout("handle_cap_flush_ack inode %p mds%d seq %d on %s cleaned %s,"
+-           " flushing %s -> %s\n",
+-           inode, session->s_mds, seq, ceph_cap_string(dirty),
+-           ceph_cap_string(cleaned), ceph_cap_string(ci->i_flushing_caps),
+-           ceph_cap_string(ci->i_flushing_caps & ~cleaned));
++      doutc(cl, "%p %llx.%llx mds%d seq %d on %s cleaned %s, flushing %s -> %s\n",
++            inode, ceph_vinop(inode), session->s_mds, seq,
++            ceph_cap_string(dirty), ceph_cap_string(cleaned),
++            ceph_cap_string(ci->i_flushing_caps),
++            ceph_cap_string(ci->i_flushing_caps & ~cleaned));
+       if (list_empty(&to_remove) && !cleaned)
+               goto out;
+@@ -3788,18 +3872,21 @@ static void handle_cap_flush_ack(struct
+               if (list_empty(&ci->i_cap_flush_list)) {
+                       list_del_init(&ci->i_flushing_item);
+                       if (!list_empty(&session->s_cap_flushing)) {
+-                              dout(" mds%d still flushing cap on %p\n",
+-                                   session->s_mds,
+-                                   &list_first_entry(&session->s_cap_flushing,
+-                                              struct ceph_inode_info,
+-                                              i_flushing_item)->netfs.inode);
++                              struct inode *inode =
++                                          &list_first_entry(&session->s_cap_flushing,
++                                                            struct ceph_inode_info,
++                                                            i_flushing_item)->netfs.inode;
++                              doutc(cl, " mds%d still flushing cap on %p %llx.%llx\n",
++                                    session->s_mds, inode, ceph_vinop(inode));
+                       }
+               }
+               mdsc->num_cap_flushing--;
+-              dout(" inode %p now !flushing\n", inode);
++              doutc(cl, " %p %llx.%llx now !flushing\n", inode,
++                    ceph_vinop(inode));
+               if (ci->i_dirty_caps == 0) {
+-                      dout(" inode %p now clean\n", inode);
++                      doutc(cl, " %p %llx.%llx now clean\n", inode,
++                            ceph_vinop(inode));
+                       BUG_ON(!list_empty(&ci->i_dirty_item));
+                       drop = true;
+                       if (ci->i_wr_ref == 0 &&
+@@ -3838,11 +3925,13 @@ void __ceph_remove_capsnap(struct inode
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       bool ret;
+       lockdep_assert_held(&ci->i_ceph_lock);
+-      dout("removing capsnap %p, inode %p ci %p\n", capsnap, inode, ci);
++      doutc(cl, "removing capsnap %p, %p %llx.%llx ci %p\n", capsnap,
++            inode, ceph_vinop(inode), ci);
+       list_del_init(&capsnap->ci_item);
+       ret = __detach_cap_flush_from_ci(ci, &capsnap->cap_flush);
+@@ -3882,28 +3971,30 @@ static void handle_cap_flushsnap_ack(str
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       u64 follows = le64_to_cpu(m->snap_follows);
+       struct ceph_cap_snap *capsnap = NULL, *iter;
+       bool wake_ci = false;
+       bool wake_mdsc = false;
+-      dout("handle_cap_flushsnap_ack inode %p ci %p mds%d follows %lld\n",
+-           inode, ci, session->s_mds, follows);
++      doutc(cl, "%p %llx.%llx ci %p mds%d follows %lld\n", inode,
++            ceph_vinop(inode), ci, session->s_mds, follows);
+       spin_lock(&ci->i_ceph_lock);
+       list_for_each_entry(iter, &ci->i_cap_snaps, ci_item) {
+               if (iter->follows == follows) {
+                       if (iter->cap_flush.tid != flush_tid) {
+-                              dout(" cap_snap %p follows %lld tid %lld !="
+-                                   " %lld\n", iter, follows,
+-                                   flush_tid, iter->cap_flush.tid);
++                              doutc(cl, " cap_snap %p follows %lld "
++                                    "tid %lld != %lld\n", iter,
++                                    follows, flush_tid,
++                                    iter->cap_flush.tid);
+                               break;
+                       }
+                       capsnap = iter;
+                       break;
+               } else {
+-                      dout(" skipping cap_snap %p follows %lld\n",
+-                           iter, iter->follows);
++                      doutc(cl, " skipping cap_snap %p follows %lld\n",
++                            iter, iter->follows);
+               }
+       }
+       if (capsnap)
+@@ -3932,6 +4023,7 @@ static bool handle_cap_trunc(struct inod
+                            struct cap_extra_info *extra_info)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int mds = session->s_mds;
+       int seq = le32_to_cpu(trunc->seq);
+       u32 truncate_seq = le32_to_cpu(trunc->truncate_seq);
+@@ -3954,8 +4046,8 @@ static bool handle_cap_trunc(struct inod
+       if (IS_ENCRYPTED(inode) && size)
+               size = extra_info->fscrypt_file_size;
+-      dout("%s inode %p mds%d seq %d to %lld truncate seq %d\n",
+-           __func__, inode, mds, seq, truncate_size, truncate_seq);
++      doutc(cl, "%p %llx.%llx mds%d seq %d to %lld truncate seq %d\n",
++            inode, ceph_vinop(inode), mds, seq, truncate_size, truncate_seq);
+       queue_trunc = ceph_fill_file_size(inode, issued,
+                                         truncate_seq, truncate_size, size);
+       return queue_trunc;
+@@ -3974,6 +4066,7 @@ static void handle_cap_export(struct ino
+                             struct ceph_mds_session *session)
+ {
+       struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_session *tsession = NULL;
+       struct ceph_cap *cap, *tcap, *new_cap = NULL;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+@@ -3993,8 +4086,8 @@ static void handle_cap_export(struct ino
+               target = -1;
+       }
+-      dout("handle_cap_export inode %p ci %p mds%d mseq %d target %d\n",
+-           inode, ci, mds, mseq, target);
++      doutc(cl, "%p %llx.%llx ci %p mds%d mseq %d target %d\n",
++            inode, ceph_vinop(inode), ci, mds, mseq, target);
+ retry:
+       down_read(&mdsc->snap_rwsem);
+       spin_lock(&ci->i_ceph_lock);
+@@ -4014,12 +4107,13 @@ retry:
+       issued = cap->issued;
+       if (issued != cap->implemented)
+-              pr_err_ratelimited("handle_cap_export: issued != implemented: "
+-                              "ino (%llx.%llx) mds%d seq %d mseq %d "
+-                              "issued %s implemented %s\n",
+-                              ceph_vinop(inode), mds, cap->seq, cap->mseq,
+-                              ceph_cap_string(issued),
+-                              ceph_cap_string(cap->implemented));
++              pr_err_ratelimited_client(cl, "issued != implemented: "
++                                        "%p %llx.%llx mds%d seq %d mseq %d"
++                                        " issued %s implemented %s\n",
++                                        inode, ceph_vinop(inode), mds,
++                                        cap->seq, cap->mseq,
++                                        ceph_cap_string(issued),
++                                        ceph_cap_string(cap->implemented));
+       tcap = __get_cap_for_mds(ci, target);
+@@ -4027,7 +4121,8 @@ retry:
+               /* already have caps from the target */
+               if (tcap->cap_id == t_cap_id &&
+                   ceph_seq_cmp(tcap->seq, t_seq) < 0) {
+-                      dout(" updating import cap %p mds%d\n", tcap, target);
++                      doutc(cl, " updating import cap %p mds%d\n", tcap,
++                            target);
+                       tcap->cap_id = t_cap_id;
+                       tcap->seq = t_seq - 1;
+                       tcap->issue_seq = t_seq - 1;
+@@ -4108,6 +4203,7 @@ static void handle_cap_import(struct cep
+                             struct ceph_cap **target_cap, int *old_issued)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_cap *cap, *ocap, *new_cap = NULL;
+       int mds = session->s_mds;
+       int issued;
+@@ -4128,8 +4224,8 @@ static void handle_cap_import(struct cep
+               peer = -1;
+       }
+-      dout("handle_cap_import inode %p ci %p mds%d mseq %d peer %d\n",
+-           inode, ci, mds, mseq, peer);
++      doutc(cl, "%p %llx.%llx ci %p mds%d mseq %d peer %d\n",
++            inode, ceph_vinop(inode), ci, mds, mseq, peer);
+ retry:
+       cap = __get_cap_for_mds(ci, mds);
+       if (!cap) {
+@@ -4155,17 +4251,17 @@ retry:
+       ocap = peer >= 0 ? __get_cap_for_mds(ci, peer) : NULL;
+       if (ocap && ocap->cap_id == p_cap_id) {
+-              dout(" remove export cap %p mds%d flags %d\n",
+-                   ocap, peer, ph->flags);
++              doutc(cl, " remove export cap %p mds%d flags %d\n",
++                    ocap, peer, ph->flags);
+               if ((ph->flags & CEPH_CAP_FLAG_AUTH) &&
+                   (ocap->seq != le32_to_cpu(ph->seq) ||
+                    ocap->mseq != le32_to_cpu(ph->mseq))) {
+-                      pr_err_ratelimited("handle_cap_import: "
+-                                      "mismatched seq/mseq: ino (%llx.%llx) "
+-                                      "mds%d seq %d mseq %d importer mds%d "
+-                                      "has peer seq %d mseq %d\n",
+-                                      ceph_vinop(inode), peer, ocap->seq,
+-                                      ocap->mseq, mds, le32_to_cpu(ph->seq),
++                      pr_err_ratelimited_client(cl, "mismatched seq/mseq: "
++                                      "%p %llx.%llx mds%d seq %d mseq %d"
++                                      " importer mds%d has peer seq %d mseq %d\n",
++                                      inode, ceph_vinop(inode), peer,
++                                      ocap->seq, ocap->mseq, mds,
++                                      le32_to_cpu(ph->seq),
+                                       le32_to_cpu(ph->mseq));
+               }
+               ceph_remove_cap(mdsc, ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
+@@ -4231,6 +4327,7 @@ void ceph_handle_caps(struct ceph_mds_se
+                     struct ceph_msg *msg)
+ {
+       struct ceph_mds_client *mdsc = session->s_mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct inode *inode;
+       struct ceph_inode_info *ci;
+       struct ceph_cap *cap;
+@@ -4249,7 +4346,7 @@ void ceph_handle_caps(struct ceph_mds_se
+       bool close_sessions = false;
+       bool do_cap_release = false;
+-      dout("handle_caps from mds%d\n", session->s_mds);
++      doutc(cl, "from mds%d\n", session->s_mds);
+       if (!ceph_inc_mds_stopping_blocker(mdsc, session))
+               return;
+@@ -4352,15 +4449,15 @@ void ceph_handle_caps(struct ceph_mds_se
+       /* lookup ino */
+       inode = ceph_find_inode(mdsc->fsc->sb, vino);
+-      dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino,
+-           vino.snap, inode);
++      doutc(cl, " op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op),
++            vino.ino, vino.snap, inode);
+       mutex_lock(&session->s_mutex);
+-      dout(" mds%d seq %lld cap seq %u\n", session->s_mds, session->s_seq,
+-           (unsigned)seq);
++      doutc(cl, " mds%d seq %lld cap seq %u\n", session->s_mds,
++            session->s_seq, (unsigned)seq);
+       if (!inode) {
+-              dout(" i don't have ino %llx\n", vino.ino);
++              doutc(cl, " i don't have ino %llx\n", vino.ino);
+               switch (op) {
+               case CEPH_CAP_OP_IMPORT:
+@@ -4415,9 +4512,9 @@ void ceph_handle_caps(struct ceph_mds_se
+       spin_lock(&ci->i_ceph_lock);
+       cap = __get_cap_for_mds(ceph_inode(inode), session->s_mds);
+       if (!cap) {
+-              dout(" no cap on %p ino %llx.%llx from mds%d\n",
+-                   inode, ceph_ino(inode), ceph_snap(inode),
+-                   session->s_mds);
++              doutc(cl, " no cap on %p ino %llx.%llx from mds%d\n",
++                    inode, ceph_ino(inode), ceph_snap(inode),
++                    session->s_mds);
+               spin_unlock(&ci->i_ceph_lock);
+               switch (op) {
+               case CEPH_CAP_OP_REVOKE:
+@@ -4455,8 +4552,8 @@ void ceph_handle_caps(struct ceph_mds_se
+       default:
+               spin_unlock(&ci->i_ceph_lock);
+-              pr_err("ceph_handle_caps: unknown cap op %d %s\n", op,
+-                     ceph_cap_op_name(op));
++              pr_err_client(cl, "unknown cap op %d %s\n", op,
++                            ceph_cap_op_name(op));
+       }
+ done:
+@@ -4497,7 +4594,7 @@ flush_cap_releases:
+       goto done;
+ bad:
+-      pr_err("ceph_handle_caps: corrupt message\n");
++      pr_err_client(cl, "corrupt message\n");
+       ceph_msg_dump(msg);
+       goto out;
+ }
+@@ -4511,6 +4608,7 @@ bad:
+  */
+ unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct inode *inode;
+       struct ceph_inode_info *ci;
+       struct ceph_mount_options *opt = mdsc->fsc->mount_options;
+@@ -4518,14 +4616,14 @@ unsigned long ceph_check_delayed_caps(st
+       unsigned long loop_start = jiffies;
+       unsigned long delay = 0;
+-      dout("check_delayed_caps\n");
++      doutc(cl, "begin\n");
+       spin_lock(&mdsc->cap_delay_lock);
+       while (!list_empty(&mdsc->cap_delay_list)) {
+               ci = list_first_entry(&mdsc->cap_delay_list,
+                                     struct ceph_inode_info,
+                                     i_cap_delay_list);
+               if (time_before(loop_start, ci->i_hold_caps_max - delay_max)) {
+-                      dout("%s caps added recently.  Exiting loop", __func__);
++                      doutc(cl, "caps added recently.  Exiting loop");
+                       delay = ci->i_hold_caps_max;
+                       break;
+               }
+@@ -4537,13 +4635,15 @@ unsigned long ceph_check_delayed_caps(st
+               inode = igrab(&ci->netfs.inode);
+               if (inode) {
+                       spin_unlock(&mdsc->cap_delay_lock);
+-                      dout("check_delayed_caps on %p\n", inode);
++                      doutc(cl, "on %p %llx.%llx\n", inode,
++                            ceph_vinop(inode));
+                       ceph_check_caps(ci, 0);
+                       iput(inode);
+                       spin_lock(&mdsc->cap_delay_lock);
+               }
+       }
+       spin_unlock(&mdsc->cap_delay_lock);
++      doutc(cl, "done\n");
+       return delay;
+ }
+@@ -4554,17 +4654,18 @@ unsigned long ceph_check_delayed_caps(st
+ static void flush_dirty_session_caps(struct ceph_mds_session *s)
+ {
+       struct ceph_mds_client *mdsc = s->s_mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *ci;
+       struct inode *inode;
+-      dout("flush_dirty_caps\n");
++      doutc(cl, "begin\n");
+       spin_lock(&mdsc->cap_dirty_lock);
+       while (!list_empty(&s->s_cap_dirty)) {
+               ci = list_first_entry(&s->s_cap_dirty, struct ceph_inode_info,
+                                     i_dirty_item);
+               inode = &ci->netfs.inode;
+               ihold(inode);
+-              dout("flush_dirty_caps %llx.%llx\n", ceph_vinop(inode));
++              doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
+               spin_unlock(&mdsc->cap_dirty_lock);
+               ceph_wait_on_async_create(inode);
+               ceph_check_caps(ci, CHECK_CAPS_FLUSH);
+@@ -4572,7 +4673,7 @@ static void flush_dirty_session_caps(str
+               spin_lock(&mdsc->cap_dirty_lock);
+       }
+       spin_unlock(&mdsc->cap_dirty_lock);
+-      dout("flush_dirty_caps done\n");
++      doutc(cl, "done\n");
+ }
+ void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc)
+@@ -4697,6 +4798,7 @@ int ceph_encode_inode_release(void **p,
+                             int mds, int drop, int unless, int force)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_cap *cap;
+       struct ceph_mds_request_release *rel = *p;
+       int used, dirty;
+@@ -4706,9 +4808,9 @@ int ceph_encode_inode_release(void **p,
+       used = __ceph_caps_used(ci);
+       dirty = __ceph_caps_dirty(ci);
+-      dout("encode_inode_release %p mds%d used|dirty %s drop %s unless %s\n",
+-           inode, mds, ceph_cap_string(used|dirty), ceph_cap_string(drop),
+-           ceph_cap_string(unless));
++      doutc(cl, "%p %llx.%llx mds%d used|dirty %s drop %s unless %s\n",
++            inode, ceph_vinop(inode), mds, ceph_cap_string(used|dirty),
++            ceph_cap_string(drop), ceph_cap_string(unless));
+       /* only drop unused, clean caps */
+       drop &= ~(used | dirty);
+@@ -4730,12 +4832,13 @@ int ceph_encode_inode_release(void **p,
+               if (force || (cap->issued & drop)) {
+                       if (cap->issued & drop) {
+                               int wanted = __ceph_caps_wanted(ci);
+-                              dout("encode_inode_release %p cap %p "
+-                                   "%s -> %s, wanted %s -> %s\n", inode, cap,
+-                                   ceph_cap_string(cap->issued),
+-                                   ceph_cap_string(cap->issued & ~drop),
+-                                   ceph_cap_string(cap->mds_wanted),
+-                                   ceph_cap_string(wanted));
++                              doutc(cl, "%p %llx.%llx cap %p %s -> %s, "
++                                    "wanted %s -> %s\n", inode,
++                                    ceph_vinop(inode), cap,
++                                    ceph_cap_string(cap->issued),
++                                    ceph_cap_string(cap->issued & ~drop),
++                                    ceph_cap_string(cap->mds_wanted),
++                                    ceph_cap_string(wanted));
+                               cap->issued &= ~drop;
+                               cap->implemented &= ~drop;
+@@ -4744,9 +4847,9 @@ int ceph_encode_inode_release(void **p,
+                                   !(wanted & CEPH_CAP_ANY_FILE_WR))
+                                       ci->i_requested_max_size = 0;
+                       } else {
+-                              dout("encode_inode_release %p cap %p %s"
+-                                   " (force)\n", inode, cap,
+-                                   ceph_cap_string(cap->issued));
++                              doutc(cl, "%p %llx.%llx cap %p %s (force)\n",
++                                    inode, ceph_vinop(inode), cap,
++                                    ceph_cap_string(cap->issued));
+                       }
+                       rel->ino = cpu_to_le64(ceph_ino(inode));
+@@ -4761,8 +4864,9 @@ int ceph_encode_inode_release(void **p,
+                       *p += sizeof(*rel);
+                       ret = 1;
+               } else {
+-                      dout("encode_inode_release %p cap %p %s (noop)\n",
+-                           inode, cap, ceph_cap_string(cap->issued));
++                      doutc(cl, "%p %llx.%llx cap %p %s (noop)\n",
++                            inode, ceph_vinop(inode), cap,
++                            ceph_cap_string(cap->issued));
+               }
+       }
+       spin_unlock(&ci->i_ceph_lock);
+@@ -4787,6 +4891,7 @@ int ceph_encode_dentry_release(void **p,
+ {
+       struct ceph_mds_request_release *rel = *p;
+       struct ceph_dentry_info *di = ceph_dentry(dentry);
++      struct ceph_client *cl;
+       int force = 0;
+       int ret;
+@@ -4806,10 +4911,11 @@ int ceph_encode_dentry_release(void **p,
+       ret = ceph_encode_inode_release(p, dir, mds, drop, unless, force);
++      cl = ceph_inode_to_client(dir);
+       spin_lock(&dentry->d_lock);
+       if (ret && di->lease_session && di->lease_session->s_mds == mds) {
+-              dout("encode_dentry_release %p mds%d seq %d\n",
+-                   dentry, mds, (int)di->lease_seq);
++              doutc(cl, "%p mds%d seq %d\n",  dentry, mds,
++                    (int)di->lease_seq);
+               rel->dname_seq = cpu_to_le32(di->lease_seq);
+               __ceph_mdsc_drop_dentry_lease(dentry);
+               spin_unlock(&dentry->d_lock);
+@@ -4835,12 +4941,14 @@ int ceph_encode_dentry_release(void **p,
+ static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_cap_snap *capsnap;
+       int capsnap_release = 0;
+       lockdep_assert_held(&ci->i_ceph_lock);
+-      dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
++      doutc(cl, "removing capsnaps, ci is %p, %p %llx.%llx\n",
++            ci, inode, ceph_vinop(inode));
+       while (!list_empty(&ci->i_cap_snaps)) {
+               capsnap = list_first_entry(&ci->i_cap_snaps,
+@@ -4859,6 +4967,7 @@ int ceph_purge_inode_cap(struct inode *i
+ {
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
++      struct ceph_client *cl = fsc->client;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       bool is_auth;
+       bool dirty_dropped = false;
+@@ -4866,8 +4975,8 @@ int ceph_purge_inode_cap(struct inode *i
+       lockdep_assert_held(&ci->i_ceph_lock);
+-      dout("removing cap %p, ci is %p, inode is %p\n",
+-           cap, ci, &ci->netfs.inode);
++      doutc(cl, "removing cap %p, ci is %p, %p %llx.%llx\n",
++            cap, ci, inode, ceph_vinop(inode));
+       is_auth = (cap == ci->i_auth_cap);
+       __ceph_remove_cap(cap, false);
+@@ -4894,19 +5003,19 @@ int ceph_purge_inode_cap(struct inode *i
+               }
+               if (!list_empty(&ci->i_dirty_item)) {
+-                      pr_warn_ratelimited(
+-                              " dropping dirty %s state for %p %lld\n",
++                      pr_warn_ratelimited_client(cl,
++                              " dropping dirty %s state for %p %llx.%llx\n",
+                               ceph_cap_string(ci->i_dirty_caps),
+-                              inode, ceph_ino(inode));
++                              inode, ceph_vinop(inode));
+                       ci->i_dirty_caps = 0;
+                       list_del_init(&ci->i_dirty_item);
+                       dirty_dropped = true;
+               }
+               if (!list_empty(&ci->i_flushing_item)) {
+-                      pr_warn_ratelimited(
+-                              " dropping dirty+flushing %s state for %p %lld\n",
++                      pr_warn_ratelimited_client(cl,
++                              " dropping dirty+flushing %s state for %p %llx.%llx\n",
+                               ceph_cap_string(ci->i_flushing_caps),
+-                              inode, ceph_ino(inode));
++                              inode, ceph_vinop(inode));
+                       ci->i_flushing_caps = 0;
+                       list_del_init(&ci->i_flushing_item);
+                       mdsc->num_cap_flushing--;
+@@ -4929,8 +5038,9 @@ int ceph_purge_inode_cap(struct inode *i
+               if (atomic_read(&ci->i_filelock_ref) > 0) {
+                       /* make further file lock syscall return -EIO */
+                       ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
+-                      pr_warn_ratelimited(" dropping file locks for %p %lld\n",
+-                                          inode, ceph_ino(inode));
++                      pr_warn_ratelimited_client(cl,
++                              " dropping file locks for %p %llx.%llx\n",
++                              inode, ceph_vinop(inode));
+               }
+               if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
+--- a/fs/ceph/crypto.c
++++ b/fs/ceph/crypto.c
+@@ -211,6 +211,7 @@ void ceph_fscrypt_as_ctx_to_req(struct c
+ static struct inode *parse_longname(const struct inode *parent,
+                                   const char *name, int *name_len)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(parent);
+       struct inode *dir = NULL;
+       struct ceph_vino vino = { .snap = CEPH_NOSNAP };
+       char *inode_number;
+@@ -222,12 +223,12 @@ static struct inode *parse_longname(cons
+       name++;
+       name_end = strrchr(name, '_');
+       if (!name_end) {
+-              dout("Failed to parse long snapshot name: %s\n", name);
++              doutc(cl, "failed to parse long snapshot name: %s\n", name);
+               return ERR_PTR(-EIO);
+       }
+       *name_len = (name_end - name);
+       if (*name_len <= 0) {
+-              pr_err("Failed to parse long snapshot name\n");
++              pr_err_client(cl, "failed to parse long snapshot name\n");
+               return ERR_PTR(-EIO);
+       }
+@@ -239,7 +240,7 @@ static struct inode *parse_longname(cons
+               return ERR_PTR(-ENOMEM);
+       ret = kstrtou64(inode_number, 10, &vino.ino);
+       if (ret) {
+-              dout("Failed to parse inode number: %s\n", name);
++              doutc(cl, "failed to parse inode number: %s\n", name);
+               dir = ERR_PTR(ret);
+               goto out;
+       }
+@@ -250,7 +251,7 @@ static struct inode *parse_longname(cons
+               /* This can happen if we're not mounting cephfs on the root */
+               dir = ceph_get_inode(parent->i_sb, vino, NULL);
+               if (IS_ERR(dir))
+-                      dout("Can't find inode %s (%s)\n", inode_number, name);
++                      doutc(cl, "can't find inode %s (%s)\n", inode_number, name);
+       }
+ out:
+@@ -261,6 +262,7 @@ out:
+ int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name,
+                               char *buf)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(parent);
+       struct inode *dir = parent;
+       struct qstr iname;
+       u32 len;
+@@ -329,7 +331,7 @@ int ceph_encode_encrypted_dname(struct i
+       /* base64 encode the encrypted name */
+       elen = ceph_base64_encode(cryptbuf, len, buf);
+-      dout("base64-encoded ciphertext name = %.*s\n", elen, buf);
++      doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, buf);
+       /* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */
+       WARN_ON(elen > 240);
+@@ -504,7 +506,10 @@ int ceph_fscrypt_decrypt_block_inplace(c
+                                 struct page *page, unsigned int len,
+                                 unsigned int offs, u64 lblk_num)
+ {
+-      dout("%s: len %u offs %u blk %llu\n", __func__, len, offs, lblk_num);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
++
++      doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode,
++            ceph_vinop(inode), len, offs, lblk_num);
+       return fscrypt_decrypt_block_inplace(inode, page, len, offs, lblk_num);
+ }
+@@ -513,7 +518,10 @@ int ceph_fscrypt_encrypt_block_inplace(c
+                                 unsigned int offs, u64 lblk_num,
+                                 gfp_t gfp_flags)
+ {
+-      dout("%s: len %u offs %u blk %llu\n", __func__, len, offs, lblk_num);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
++
++      doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode,
++            ceph_vinop(inode), len, offs, lblk_num);
+       return fscrypt_encrypt_block_inplace(inode, page, len, offs, lblk_num,
+                                            gfp_flags);
+ }
+@@ -582,6 +590,7 @@ int ceph_fscrypt_decrypt_extents(struct
+                                u64 off, struct ceph_sparse_extent *map,
+                                u32 ext_cnt)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int i, ret = 0;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       u64 objno, objoff;
+@@ -589,7 +598,8 @@ int ceph_fscrypt_decrypt_extents(struct
+       /* Nothing to do for empty array */
+       if (ext_cnt == 0) {
+-              dout("%s: empty array, ret 0\n", __func__);
++              doutc(cl, "%p %llx.%llx empty array, ret 0\n", inode,
++                    ceph_vinop(inode));
+               return 0;
+       }
+@@ -603,14 +613,17 @@ int ceph_fscrypt_decrypt_extents(struct
+               int fret;
+               if ((ext->off | ext->len) & ~CEPH_FSCRYPT_BLOCK_MASK) {
+-                      pr_warn("%s: bad encrypted sparse extent idx %d off %llx len %llx\n",
+-                              __func__, i, ext->off, ext->len);
++                      pr_warn_client(cl,
++                              "%p %llx.%llx bad encrypted sparse extent "
++                              "idx %d off %llx len %llx\n",
++                              inode, ceph_vinop(inode), i, ext->off,
++                              ext->len);
+                       return -EIO;
+               }
+               fret = ceph_fscrypt_decrypt_pages(inode, &page[pgidx],
+                                                off + pgsoff, ext->len);
+-              dout("%s: [%d] 0x%llx~0x%llx fret %d\n", __func__, i,
+-                              ext->off, ext->len, fret);
++              doutc(cl, "%p %llx.%llx [%d] 0x%llx~0x%llx fret %d\n", inode,
++                    ceph_vinop(inode), i, ext->off, ext->len, fret);
+               if (fret < 0) {
+                       if (ret == 0)
+                               ret = fret;
+@@ -618,7 +631,7 @@ int ceph_fscrypt_decrypt_extents(struct
+               }
+               ret = pgsoff + fret;
+       }
+-      dout("%s: ret %d\n", __func__, ret);
++      doutc(cl, "ret %d\n", ret);
+       return ret;
+ }
+--- a/fs/ceph/debugfs.c
++++ b/fs/ceph/debugfs.c
+@@ -398,7 +398,7 @@ DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fo
+ void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
+ {
+-      dout("ceph_fs_debugfs_cleanup\n");
++      doutc(fsc->client, "begin\n");
+       debugfs_remove(fsc->debugfs_bdi);
+       debugfs_remove(fsc->debugfs_congestion_kb);
+       debugfs_remove(fsc->debugfs_mdsmap);
+@@ -407,13 +407,14 @@ void ceph_fs_debugfs_cleanup(struct ceph
+       debugfs_remove(fsc->debugfs_status);
+       debugfs_remove(fsc->debugfs_mdsc);
+       debugfs_remove_recursive(fsc->debugfs_metrics_dir);
++      doutc(fsc->client, "done\n");
+ }
+ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
+ {
+       char name[100];
+-      dout("ceph_fs_debugfs_init\n");
++      doutc(fsc->client, "begin\n");
+       fsc->debugfs_congestion_kb =
+               debugfs_create_file("writeback_congestion_kb",
+                                   0600,
+@@ -469,6 +470,7 @@ void ceph_fs_debugfs_init(struct ceph_fs
+                           &metrics_size_fops);
+       debugfs_create_file("caps", 0400, fsc->debugfs_metrics_dir, fsc,
+                           &metrics_caps_fops);
++      doutc(fsc->client, "done\n");
+ }
+--- a/fs/ceph/dir.c
++++ b/fs/ceph/dir.c
+@@ -109,7 +109,9 @@ static int fpos_cmp(loff_t l, loff_t r)
+  * regardless of what dir changes take place on the
+  * server.
+  */
+-static int note_last_dentry(struct ceph_dir_file_info *dfi, const char *name,
++static int note_last_dentry(struct ceph_fs_client *fsc,
++                          struct ceph_dir_file_info *dfi,
++                          const char *name,
+                           int len, unsigned next_offset)
+ {
+       char *buf = kmalloc(len+1, GFP_KERNEL);
+@@ -120,7 +122,7 @@ static int note_last_dentry(struct ceph_
+       memcpy(dfi->last_name, name, len);
+       dfi->last_name[len] = 0;
+       dfi->next_offset = next_offset;
+-      dout("note_last_dentry '%s'\n", dfi->last_name);
++      doutc(fsc->client, "'%s'\n", dfi->last_name);
+       return 0;
+ }
+@@ -130,6 +132,7 @@ __dcache_find_get_entry(struct dentry *p
+                       struct ceph_readdir_cache_control *cache_ctl)
+ {
+       struct inode *dir = d_inode(parent);
++      struct ceph_client *cl = ceph_inode_to_client(dir);
+       struct dentry *dentry;
+       unsigned idx_mask = (PAGE_SIZE / sizeof(struct dentry *)) - 1;
+       loff_t ptr_pos = idx * sizeof(struct dentry *);
+@@ -142,7 +145,7 @@ __dcache_find_get_entry(struct dentry *p
+               ceph_readdir_cache_release(cache_ctl);
+               cache_ctl->page = find_lock_page(&dir->i_data, ptr_pgoff);
+               if (!cache_ctl->page) {
+-                      dout(" page %lu not found\n", ptr_pgoff);
++                      doutc(cl, " page %lu not found\n", ptr_pgoff);
+                       return ERR_PTR(-EAGAIN);
+               }
+               /* reading/filling the cache are serialized by
+@@ -185,13 +188,16 @@ static int __dcache_readdir(struct file
+       struct ceph_dir_file_info *dfi = file->private_data;
+       struct dentry *parent = file->f_path.dentry;
+       struct inode *dir = d_inode(parent);
++      struct ceph_fs_client *fsc = ceph_inode_to_fs_client(dir);
++      struct ceph_client *cl = ceph_inode_to_client(dir);
+       struct dentry *dentry, *last = NULL;
+       struct ceph_dentry_info *di;
+       struct ceph_readdir_cache_control cache_ctl = {};
+       u64 idx = 0;
+       int err = 0;
+-      dout("__dcache_readdir %p v%u at %llx\n", dir, (unsigned)shared_gen, ctx->pos);
++      doutc(cl, "%p %llx.%llx v%u at %llx\n", dir, ceph_vinop(dir),
++            (unsigned)shared_gen, ctx->pos);
+       /* search start position */
+       if (ctx->pos > 2) {
+@@ -221,7 +227,8 @@ static int __dcache_readdir(struct file
+                       dput(dentry);
+               }
+-              dout("__dcache_readdir %p cache idx %llu\n", dir, idx);
++              doutc(cl, "%p %llx.%llx cache idx %llu\n", dir,
++                    ceph_vinop(dir), idx);
+       }
+@@ -257,8 +264,8 @@ static int __dcache_readdir(struct file
+               spin_unlock(&dentry->d_lock);
+               if (emit_dentry) {
+-                      dout(" %llx dentry %p %pd %p\n", di->offset,
+-                           dentry, dentry, d_inode(dentry));
++                      doutc(cl, " %llx dentry %p %pd %p\n", di->offset,
++                            dentry, dentry, d_inode(dentry));
+                       ctx->pos = di->offset;
+                       if (!dir_emit(ctx, dentry->d_name.name,
+                                     dentry->d_name.len, ceph_present_inode(d_inode(dentry)),
+@@ -281,7 +288,8 @@ out:
+       if (last) {
+               int ret;
+               di = ceph_dentry(last);
+-              ret = note_last_dentry(dfi, last->d_name.name, last->d_name.len,
++              ret = note_last_dentry(fsc, dfi, last->d_name.name,
++                                     last->d_name.len,
+                                      fpos_off(di->offset) + 1);
+               if (ret < 0)
+                       err = ret;
+@@ -312,18 +320,21 @@ static int ceph_readdir(struct file *fil
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
++      struct ceph_client *cl = fsc->client;
+       int i;
+       int err;
+       unsigned frag = -1;
+       struct ceph_mds_reply_info_parsed *rinfo;
+-      dout("readdir %p file %p pos %llx\n", inode, file, ctx->pos);
++      doutc(cl, "%p %llx.%llx file %p pos %llx\n", inode,
++            ceph_vinop(inode), file, ctx->pos);
+       if (dfi->file_info.flags & CEPH_F_ATEND)
+               return 0;
+       /* always start with . and .. */
+       if (ctx->pos == 0) {
+-              dout("readdir off 0 -> '.'\n");
++              doutc(cl, "%p %llx.%llx off 0 -> '.'\n", inode,
++                    ceph_vinop(inode));
+               if (!dir_emit(ctx, ".", 1, ceph_present_inode(inode),
+                           inode->i_mode >> 12))
+                       return 0;
+@@ -337,7 +348,8 @@ static int ceph_readdir(struct file *fil
+               ino = ceph_present_inode(dentry->d_parent->d_inode);
+               spin_unlock(&dentry->d_lock);
+-              dout("readdir off 1 -> '..'\n");
++              doutc(cl, "%p %llx.%llx off 1 -> '..'\n", inode,
++                    ceph_vinop(inode));
+               if (!dir_emit(ctx, "..", 2, ino, inode->i_mode >> 12))
+                       return 0;
+               ctx->pos = 2;
+@@ -391,8 +403,8 @@ more:
+                       frag = fpos_frag(ctx->pos);
+               }
+-              dout("readdir fetching %llx.%llx frag %x offset '%s'\n",
+-                   ceph_vinop(inode), frag, dfi->last_name);
++              doutc(cl, "fetching %p %llx.%llx frag %x offset '%s'\n",
++                    inode, ceph_vinop(inode), frag, dfi->last_name);
+               req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
+               if (IS_ERR(req))
+                       return PTR_ERR(req);
+@@ -446,12 +458,12 @@ more:
+                       ceph_mdsc_put_request(req);
+                       return err;
+               }
+-              dout("readdir got and parsed readdir result=%d on "
+-                   "frag %x, end=%d, complete=%d, hash_order=%d\n",
+-                   err, frag,
+-                   (int)req->r_reply_info.dir_end,
+-                   (int)req->r_reply_info.dir_complete,
+-                   (int)req->r_reply_info.hash_order);
++              doutc(cl, "%p %llx.%llx got and parsed readdir result=%d"
++                    "on frag %x, end=%d, complete=%d, hash_order=%d\n",
++                    inode, ceph_vinop(inode), err, frag,
++                    (int)req->r_reply_info.dir_end,
++                    (int)req->r_reply_info.dir_complete,
++                    (int)req->r_reply_info.hash_order);
+               rinfo = &req->r_reply_info;
+               if (le32_to_cpu(rinfo->dir_dir->frag) != frag) {
+@@ -481,7 +493,8 @@ more:
+                               dfi->dir_ordered_count = req->r_dir_ordered_cnt;
+                       }
+               } else {
+-                      dout("readdir !did_prepopulate\n");
++                      doutc(cl, "%p %llx.%llx !did_prepopulate\n", inode,
++                            ceph_vinop(inode));
+                       /* disable readdir cache */
+                       dfi->readdir_cache_idx = -1;
+                       /* preclude from marking dir complete */
+@@ -494,8 +507,8 @@ more:
+                                       rinfo->dir_entries + (rinfo->dir_nr-1);
+                       unsigned next_offset = req->r_reply_info.dir_end ?
+                                       2 : (fpos_off(rde->offset) + 1);
+-                      err = note_last_dentry(dfi, rde->name, rde->name_len,
+-                                             next_offset);
++                      err = note_last_dentry(fsc, dfi, rde->name,
++                                             rde->name_len, next_offset);
+                       if (err) {
+                               ceph_mdsc_put_request(dfi->last_readdir);
+                               dfi->last_readdir = NULL;
+@@ -508,9 +521,9 @@ more:
+       }
+       rinfo = &dfi->last_readdir->r_reply_info;
+-      dout("readdir frag %x num %d pos %llx chunk first %llx\n",
+-           dfi->frag, rinfo->dir_nr, ctx->pos,
+-           rinfo->dir_nr ? rinfo->dir_entries[0].offset : 0LL);
++      doutc(cl, "%p %llx.%llx frag %x num %d pos %llx chunk first %llx\n",
++            inode, ceph_vinop(inode), dfi->frag, rinfo->dir_nr, ctx->pos,
++            rinfo->dir_nr ? rinfo->dir_entries[0].offset : 0LL);
+       i = 0;
+       /* search start position */
+@@ -530,8 +543,9 @@ more:
+               struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;
+               if (rde->offset < ctx->pos) {
+-                      pr_warn("%s: rde->offset 0x%llx ctx->pos 0x%llx\n",
+-                              __func__, rde->offset, ctx->pos);
++                      pr_warn_client(cl,
++                              "%p %llx.%llx rde->offset 0x%llx ctx->pos 0x%llx\n",
++                              inode, ceph_vinop(inode), rde->offset, ctx->pos);
+                       return -EIO;
+               }
+@@ -539,9 +553,9 @@ more:
+                       return -EIO;
+               ctx->pos = rde->offset;
+-              dout("readdir (%d/%d) -> %llx '%.*s' %p\n",
+-                   i, rinfo->dir_nr, ctx->pos,
+-                   rde->name_len, rde->name, &rde->inode.in);
++              doutc(cl, "%p %llx.%llx (%d/%d) -> %llx '%.*s' %p\n", inode,
++                    ceph_vinop(inode), i, rinfo->dir_nr, ctx->pos,
++                    rde->name_len, rde->name, &rde->inode.in);
+               if (!dir_emit(ctx, rde->name, rde->name_len,
+                             ceph_present_ino(inode->i_sb, le64_to_cpu(rde->inode.in->ino)),
+@@ -552,7 +566,7 @@ more:
+                        * doesn't have enough memory, etc. So for next readdir
+                        * it will continue.
+                        */
+-                      dout("filldir stopping us...\n");
++                      doutc(cl, "filldir stopping us...\n");
+                       return 0;
+               }
+@@ -583,7 +597,8 @@ more:
+                       kfree(dfi->last_name);
+                       dfi->last_name = NULL;
+               }
+-              dout("readdir next frag is %x\n", frag);
++              doutc(cl, "%p %llx.%llx next frag is %x\n", inode,
++                    ceph_vinop(inode), frag);
+               goto more;
+       }
+       dfi->file_info.flags |= CEPH_F_ATEND;
+@@ -598,20 +613,23 @@ more:
+               spin_lock(&ci->i_ceph_lock);
+               if (dfi->dir_ordered_count ==
+                               atomic64_read(&ci->i_ordered_count)) {
+-                      dout(" marking %p complete and ordered\n", inode);
++                      doutc(cl, " marking %p %llx.%llx complete and ordered\n",
++                            inode, ceph_vinop(inode));
+                       /* use i_size to track number of entries in
+                        * readdir cache */
+                       BUG_ON(dfi->readdir_cache_idx < 0);
+                       i_size_write(inode, dfi->readdir_cache_idx *
+                                    sizeof(struct dentry*));
+               } else {
+-                      dout(" marking %p complete\n", inode);
++                      doutc(cl, " marking %llx.%llx complete\n",
++                            ceph_vinop(inode));
+               }
+               __ceph_dir_set_complete(ci, dfi->dir_release_count,
+                                       dfi->dir_ordered_count);
+               spin_unlock(&ci->i_ceph_lock);
+       }
+-      dout("readdir %p file %p done.\n", inode, file);
++      doutc(cl, "%p %llx.%llx file %p done.\n", inode, ceph_vinop(inode),
++            file);
+       return 0;
+ }
+@@ -657,6 +675,7 @@ static loff_t ceph_dir_llseek(struct fil
+ {
+       struct ceph_dir_file_info *dfi = file->private_data;
+       struct inode *inode = file->f_mapping->host;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       loff_t retval;
+       inode_lock(inode);
+@@ -676,7 +695,8 @@ static loff_t ceph_dir_llseek(struct fil
+       if (offset >= 0) {
+               if (need_reset_readdir(dfi, offset)) {
+-                      dout("dir_llseek dropping %p content\n", file);
++                      doutc(cl, "%p %llx.%llx dropping %p content\n",
++                            inode, ceph_vinop(inode), file);
+                       reset_readdir(dfi);
+               } else if (is_hash_order(offset) && offset > file->f_pos) {
+                       /* for hash offset, we don't know if a forward seek
+@@ -705,6 +725,7 @@ struct dentry *ceph_handle_snapdir(struc
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
+       struct inode *parent = d_inode(dentry->d_parent); /* we hold i_rwsem */
++      struct ceph_client *cl = ceph_inode_to_client(parent);
+       /* .snap dir? */
+       if (ceph_snap(parent) == CEPH_NOSNAP &&
+@@ -713,8 +734,9 @@ struct dentry *ceph_handle_snapdir(struc
+               struct inode *inode = ceph_get_snapdir(parent);
+               res = d_splice_alias(inode, dentry);
+-              dout("ENOENT on snapdir %p '%pd', linking to snapdir %p. Spliced dentry %p\n",
+-                   dentry, dentry, inode, res);
++              doutc(cl, "ENOENT on snapdir %p '%pd', linking to "
++                    "snapdir %p %llx.%llx. Spliced dentry %p\n",
++                    dentry, dentry, inode, ceph_vinop(inode), res);
+               if (res)
+                       dentry = res;
+       }
+@@ -735,12 +757,15 @@ struct dentry *ceph_handle_snapdir(struc
+ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
+                                 struct dentry *dentry, int err)
+ {
++      struct ceph_client *cl = req->r_mdsc->fsc->client;
++
+       if (err == -ENOENT) {
+               /* no trace? */
+               err = 0;
+               if (!req->r_reply_info.head->is_dentry) {
+-                      dout("ENOENT and no trace, dentry %p inode %p\n",
+-                           dentry, d_inode(dentry));
++                      doutc(cl,
++                            "ENOENT and no trace, dentry %p inode %llx.%llx\n",
++                            dentry, ceph_vinop(d_inode(dentry)));
+                       if (d_really_is_positive(dentry)) {
+                               d_drop(dentry);
+                               err = -ENOENT;
+@@ -774,13 +799,14 @@ static struct dentry *ceph_lookup(struct
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_mds_request *req;
+       int op;
+       int mask;
+       int err;
+-      dout("lookup %p dentry %p '%pd'\n",
+-           dir, dentry, dentry);
++      doutc(cl, "%p %llx.%llx/'%pd' dentry %p\n", dir, ceph_vinop(dir),
++            dentry, dentry);
+       if (dentry->d_name.len > NAME_MAX)
+               return ERR_PTR(-ENAMETOOLONG);
+@@ -803,7 +829,8 @@ static struct dentry *ceph_lookup(struct
+               struct ceph_dentry_info *di = ceph_dentry(dentry);
+               spin_lock(&ci->i_ceph_lock);
+-              dout(" dir %p flags are 0x%lx\n", dir, ci->i_ceph_flags);
++              doutc(cl, " dir %llx.%llx flags are 0x%lx\n",
++                    ceph_vinop(dir), ci->i_ceph_flags);
+               if (strncmp(dentry->d_name.name,
+                           fsc->mount_options->snapdir_name,
+                           dentry->d_name.len) &&
+@@ -813,7 +840,8 @@ static struct dentry *ceph_lookup(struct
+                   __ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) {
+                       __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD);
+                       spin_unlock(&ci->i_ceph_lock);
+-                      dout(" dir %p complete, -ENOENT\n", dir);
++                      doutc(cl, " dir %llx.%llx complete, -ENOENT\n",
++                            ceph_vinop(dir));
+                       if (d_unhashed(dentry))
+                               d_add(dentry, NULL);
+                       di->lease_shared_gen = atomic_read(&ci->i_shared_gen);
+@@ -852,7 +880,7 @@ static struct dentry *ceph_lookup(struct
+       }
+       dentry = ceph_finish_lookup(req, dentry, err);
+       ceph_mdsc_put_request(req);  /* will dput(dentry) */
+-      dout("lookup result=%p\n", dentry);
++      doutc(cl, "result=%p\n", dentry);
+       return dentry;
+ }
+@@ -887,6 +915,7 @@ static int ceph_mknod(struct mnt_idmap *
+                     struct dentry *dentry, umode_t mode, dev_t rdev)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       struct ceph_acl_sec_ctx as_ctx = {};
+       int err;
+@@ -903,8 +932,8 @@ static int ceph_mknod(struct mnt_idmap *
+               goto out;
+       }
+-      dout("mknod in dir %p dentry %p mode 0%ho rdev %d\n",
+-           dir, dentry, mode, rdev);
++      doutc(cl, "%p %llx.%llx/'%pd' dentry %p mode 0%ho rdev %d\n",
++            dir, ceph_vinop(dir), dentry, dentry, mode, rdev);
+       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_MKNOD, USE_AUTH_MDS);
+       if (IS_ERR(req)) {
+               err = PTR_ERR(req);
+@@ -995,6 +1024,7 @@ static int ceph_symlink(struct mnt_idmap
+                       struct dentry *dentry, const char *dest)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       struct ceph_acl_sec_ctx as_ctx = {};
+       umode_t mode = S_IFLNK | 0777;
+@@ -1012,7 +1042,8 @@ static int ceph_symlink(struct mnt_idmap
+               goto out;
+       }
+-      dout("symlink in dir %p dentry %p to '%s'\n", dir, dentry, dest);
++      doutc(cl, "%p %llx.%llx/'%pd' to '%s'\n", dir, ceph_vinop(dir), dentry,
++            dest);
+       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SYMLINK, USE_AUTH_MDS);
+       if (IS_ERR(req)) {
+               err = PTR_ERR(req);
+@@ -1066,6 +1097,7 @@ static int ceph_mkdir(struct mnt_idmap *
+                     struct dentry *dentry, umode_t mode)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       struct ceph_acl_sec_ctx as_ctx = {};
+       int err;
+@@ -1078,10 +1110,11 @@ static int ceph_mkdir(struct mnt_idmap *
+       if (ceph_snap(dir) == CEPH_SNAPDIR) {
+               /* mkdir .snap/foo is a MKSNAP */
+               op = CEPH_MDS_OP_MKSNAP;
+-              dout("mksnap dir %p snap '%pd' dn %p\n", dir,
+-                   dentry, dentry);
++              doutc(cl, "mksnap %llx.%llx/'%pd' dentry %p\n",
++                    ceph_vinop(dir), dentry, dentry);
+       } else if (ceph_snap(dir) == CEPH_NOSNAP) {
+-              dout("mkdir dir %p dn %p mode 0%ho\n", dir, dentry, mode);
++              doutc(cl, "mkdir %llx.%llx/'%pd' dentry %p mode 0%ho\n",
++                    ceph_vinop(dir), dentry, dentry, mode);
+               op = CEPH_MDS_OP_MKDIR;
+       } else {
+               err = -EROFS;
+@@ -1146,6 +1179,7 @@ static int ceph_link(struct dentry *old_
+                    struct dentry *dentry)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       int err;
+@@ -1163,8 +1197,8 @@ static int ceph_link(struct dentry *old_
+       if (err)
+               return err;
+-      dout("link in dir %p %llx.%llx old_dentry %p:'%pd' dentry %p:'%pd'\n",
+-           dir, ceph_vinop(dir), old_dentry, old_dentry, dentry, dentry);
++      doutc(cl, "%p %llx.%llx/'%pd' to '%pd'\n", dir, ceph_vinop(dir),
++            old_dentry, dentry);
+       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LINK, USE_AUTH_MDS);
+       if (IS_ERR(req)) {
+               d_drop(dentry);
+@@ -1202,13 +1236,15 @@ static void ceph_async_unlink_cb(struct
+ {
+       struct dentry *dentry = req->r_dentry;
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_dentry_info *di = ceph_dentry(dentry);
+       int result = req->r_err ? req->r_err :
+                       le32_to_cpu(req->r_reply_info.head->result);
+       if (!test_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags))
+-              pr_warn("%s dentry %p:%pd async unlink bit is not set\n",
+-                      __func__, dentry, dentry);
++              pr_warn_client(cl,
++                      "dentry %p:%pd async unlink bit is not set\n",
++                      dentry, dentry);
+       spin_lock(&fsc->async_unlink_conflict_lock);
+       hash_del_rcu(&di->hnode);
+@@ -1241,8 +1277,8 @@ static void ceph_async_unlink_cb(struct
+               /* mark inode itself for an error (since metadata is bogus) */
+               mapping_set_error(req->r_old_inode->i_mapping, result);
+-              pr_warn("async unlink failure path=(%llx)%s result=%d!\n",
+-                      base, IS_ERR(path) ? "<<bad>>" : path, result);
++              pr_warn_client(cl, "failure path=(%llx)%s result=%d!\n",
++                             base, IS_ERR(path) ? "<<bad>>" : path, result);
+               ceph_mdsc_free_path(path, pathlen);
+       }
+ out:
+@@ -1292,6 +1328,7 @@ static int get_caps_for_async_unlink(str
+ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       struct inode *inode = d_inode(dentry);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+@@ -1302,11 +1339,12 @@ static int ceph_unlink(struct inode *dir
+       if (ceph_snap(dir) == CEPH_SNAPDIR) {
+               /* rmdir .snap/foo is RMSNAP */
+-              dout("rmsnap dir %p '%pd' dn %p\n", dir, dentry, dentry);
++              doutc(cl, "rmsnap %llx.%llx/'%pd' dn\n", ceph_vinop(dir),
++                    dentry);
+               op = CEPH_MDS_OP_RMSNAP;
+       } else if (ceph_snap(dir) == CEPH_NOSNAP) {
+-              dout("unlink/rmdir dir %p dn %p inode %p\n",
+-                   dir, dentry, inode);
++              doutc(cl, "unlink/rmdir %llx.%llx/'%pd' inode %llx.%llx\n",
++                    ceph_vinop(dir), dentry, ceph_vinop(inode));
+               op = d_is_dir(dentry) ?
+                       CEPH_MDS_OP_RMDIR : CEPH_MDS_OP_UNLINK;
+       } else
+@@ -1329,9 +1367,9 @@ retry:
+           (req->r_dir_caps = get_caps_for_async_unlink(dir, dentry))) {
+               struct ceph_dentry_info *di = ceph_dentry(dentry);
+-              dout("async unlink on %llu/%.*s caps=%s", ceph_ino(dir),
+-                   dentry->d_name.len, dentry->d_name.name,
+-                   ceph_cap_string(req->r_dir_caps));
++              doutc(cl, "async unlink on %llx.%llx/'%pd' caps=%s",
++                    ceph_vinop(dir), dentry,
++                    ceph_cap_string(req->r_dir_caps));
+               set_bit(CEPH_MDS_R_ASYNC, &req->r_req_flags);
+               req->r_callback = ceph_async_unlink_cb;
+               req->r_old_inode = d_inode(dentry);
+@@ -1398,6 +1436,7 @@ static int ceph_rename(struct mnt_idmap
+                      struct dentry *new_dentry, unsigned int flags)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(old_dir->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       int op = CEPH_MDS_OP_RENAME;
+       int err;
+@@ -1427,8 +1466,9 @@ static int ceph_rename(struct mnt_idmap
+       if (err)
+               return err;
+-      dout("rename dir %p dentry %p to dir %p dentry %p\n",
+-           old_dir, old_dentry, new_dir, new_dentry);
++      doutc(cl, "%llx.%llx/'%pd' to %llx.%llx/'%pd'\n",
++            ceph_vinop(old_dir), old_dentry, ceph_vinop(new_dir),
++            new_dentry);
+       req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+@@ -1473,9 +1513,10 @@ static int ceph_rename(struct mnt_idmap
+ void __ceph_dentry_lease_touch(struct ceph_dentry_info *di)
+ {
+       struct dentry *dn = di->dentry;
+-      struct ceph_mds_client *mdsc;
++      struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+-      dout("dentry_lease_touch %p %p '%pd'\n", di, dn, dn);
++      doutc(cl, "%p %p '%pd'\n", di, dn, dn);
+       di->flags |= CEPH_DENTRY_LEASE_LIST;
+       if (di->flags & CEPH_DENTRY_SHRINK_LIST) {
+@@ -1483,7 +1524,6 @@ void __ceph_dentry_lease_touch(struct ce
+               return;
+       }
+-      mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
+       spin_lock(&mdsc->dentry_list_lock);
+       list_move_tail(&di->lease_list, &mdsc->dentry_leases);
+       spin_unlock(&mdsc->dentry_list_lock);
+@@ -1507,10 +1547,10 @@ static void __dentry_dir_lease_touch(str
+ void __ceph_dentry_dir_lease_touch(struct ceph_dentry_info *di)
+ {
+       struct dentry *dn = di->dentry;
+-      struct ceph_mds_client *mdsc;
++      struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+-      dout("dentry_dir_lease_touch %p %p '%pd' (offset 0x%llx)\n",
+-           di, dn, dn, di->offset);
++      doutc(cl, "%p %p '%pd' (offset 0x%llx)\n", di, dn, dn, di->offset);
+       if (!list_empty(&di->lease_list)) {
+               if (di->flags & CEPH_DENTRY_LEASE_LIST) {
+@@ -1530,7 +1570,6 @@ void __ceph_dentry_dir_lease_touch(struc
+               return;
+       }
+-      mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
+       spin_lock(&mdsc->dentry_list_lock);
+       __dentry_dir_lease_touch(mdsc, di),
+       spin_unlock(&mdsc->dentry_list_lock);
+@@ -1771,6 +1810,8 @@ static int dentry_lease_is_valid(struct
+ {
+       struct ceph_dentry_info *di;
+       struct ceph_mds_session *session = NULL;
++      struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dentry->d_sb)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       u32 seq = 0;
+       int valid = 0;
+@@ -1803,7 +1844,7 @@ static int dentry_lease_is_valid(struct
+                                        CEPH_MDS_LEASE_RENEW, seq);
+               ceph_put_mds_session(session);
+       }
+-      dout("dentry_lease_is_valid - dentry %p = %d\n", dentry, valid);
++      doutc(cl, "dentry %p = %d\n", dentry, valid);
+       return valid;
+ }
+@@ -1846,6 +1887,7 @@ static int dir_lease_is_valid(struct ino
+                             struct ceph_mds_client *mdsc)
+ {
+       struct ceph_inode_info *ci = ceph_inode(dir);
++      struct ceph_client *cl = mdsc->fsc->client;
+       int valid;
+       int shared_gen;
+@@ -1867,8 +1909,9 @@ static int dir_lease_is_valid(struct ino
+                       valid = 0;
+               spin_unlock(&dentry->d_lock);
+       }
+-      dout("dir_lease_is_valid dir %p v%u dentry %p = %d\n",
+-           dir, (unsigned)atomic_read(&ci->i_shared_gen), dentry, valid);
++      doutc(cl, "dir %p %llx.%llx v%u dentry %p '%pd' = %d\n", dir,
++            ceph_vinop(dir), (unsigned)atomic_read(&ci->i_shared_gen),
++            dentry, dentry, valid);
+       return valid;
+ }
+@@ -1877,10 +1920,11 @@ static int dir_lease_is_valid(struct ino
+  */
+ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
+ {
++      struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dentry->d_sb)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       int valid = 0;
+       struct dentry *parent;
+       struct inode *dir, *inode;
+-      struct ceph_mds_client *mdsc;
+       valid = fscrypt_d_revalidate(dentry, flags);
+       if (valid <= 0)
+@@ -1898,16 +1942,16 @@ static int ceph_d_revalidate(struct dent
+               inode = d_inode(dentry);
+       }
+-      dout("d_revalidate %p '%pd' inode %p offset 0x%llx nokey %d\n", dentry,
+-           dentry, inode, ceph_dentry(dentry)->offset,
+-           !!(dentry->d_flags & DCACHE_NOKEY_NAME));
++      doutc(cl, "%p '%pd' inode %p offset 0x%llx nokey %d\n",
++            dentry, dentry, inode, ceph_dentry(dentry)->offset,
++            !!(dentry->d_flags & DCACHE_NOKEY_NAME));
+       mdsc = ceph_sb_to_fs_client(dir->i_sb)->mdsc;
+       /* always trust cached snapped dentries, snapdir dentry */
+       if (ceph_snap(dir) != CEPH_NOSNAP) {
+-              dout("d_revalidate %p '%pd' inode %p is SNAPPED\n", dentry,
+-                   dentry, inode);
++              doutc(cl, "%p '%pd' inode %p is SNAPPED\n", dentry,
++                    dentry, inode);
+               valid = 1;
+       } else if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
+               valid = 1;
+@@ -1962,14 +2006,14 @@ static int ceph_d_revalidate(struct dent
+                               break;
+                       }
+                       ceph_mdsc_put_request(req);
+-                      dout("d_revalidate %p lookup result=%d\n",
+-                           dentry, err);
++                      doutc(cl, "%p '%pd', lookup result=%d\n", dentry,
++                            dentry, err);
+               }
+       } else {
+               percpu_counter_inc(&mdsc->metric.d_lease_hit);
+       }
+-      dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
++      doutc(cl, "%p '%pd' %s\n", dentry, dentry, valid ? "valid" : "invalid");
+       if (!valid)
+               ceph_dir_clear_complete(dir);
+@@ -2011,7 +2055,7 @@ static void ceph_d_release(struct dentry
+       struct ceph_dentry_info *di = ceph_dentry(dentry);
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
+-      dout("d_release %p\n", dentry);
++      doutc(fsc->client, "dentry %p '%pd'\n", dentry, dentry);
+       atomic64_dec(&fsc->mdsc->metric.total_dentries);
+@@ -2032,10 +2076,12 @@ static void ceph_d_release(struct dentry
+  */
+ static void ceph_d_prune(struct dentry *dentry)
+ {
++      struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dentry->d_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *dir_ci;
+       struct ceph_dentry_info *di;
+-      dout("ceph_d_prune %pd %p\n", dentry, dentry);
++      doutc(cl, "dentry %p '%pd'\n", dentry, dentry);
+       /* do we have a valid parent? */
+       if (IS_ROOT(dentry))
+--- a/fs/ceph/export.c
++++ b/fs/ceph/export.c
+@@ -36,6 +36,7 @@ struct ceph_nfs_snapfh {
+ static int ceph_encode_snapfh(struct inode *inode, u32 *rawfh, int *max_len,
+                             struct inode *parent_inode)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       static const int snap_handle_length =
+               sizeof(struct ceph_nfs_snapfh) >> 2;
+       struct ceph_nfs_snapfh *sfh = (void *)rawfh;
+@@ -79,13 +80,14 @@ static int ceph_encode_snapfh(struct ino
+       *max_len = snap_handle_length;
+       ret = FILEID_BTRFS_WITH_PARENT;
+ out:
+-      dout("encode_snapfh %llx.%llx ret=%d\n", ceph_vinop(inode), ret);
++      doutc(cl, "%p %llx.%llx ret=%d\n", inode, ceph_vinop(inode), ret);
+       return ret;
+ }
+ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
+                         struct inode *parent_inode)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       static const int handle_length =
+               sizeof(struct ceph_nfs_fh) >> 2;
+       static const int connected_handle_length =
+@@ -105,15 +107,15 @@ static int ceph_encode_fh(struct inode *
+       if (parent_inode) {
+               struct ceph_nfs_confh *cfh = (void *)rawfh;
+-              dout("encode_fh %llx with parent %llx\n",
+-                   ceph_ino(inode), ceph_ino(parent_inode));
++              doutc(cl, "%p %llx.%llx with parent %p %llx.%llx\n", inode,
++                    ceph_vinop(inode), parent_inode, ceph_vinop(parent_inode));
+               cfh->ino = ceph_ino(inode);
+               cfh->parent_ino = ceph_ino(parent_inode);
+               *max_len = connected_handle_length;
+               type = FILEID_INO32_GEN_PARENT;
+       } else {
+               struct ceph_nfs_fh *fh = (void *)rawfh;
+-              dout("encode_fh %llx\n", ceph_ino(inode));
++              doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
+               fh->ino = ceph_ino(inode);
+               *max_len = handle_length;
+               type = FILEID_INO32_GEN;
+@@ -206,6 +208,7 @@ static struct dentry *__snapfh_to_dentry
+                                         bool want_parent)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(sb)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       struct inode *inode;
+       struct ceph_vino vino;
+@@ -278,11 +281,10 @@ static struct dentry *__snapfh_to_dentry
+       ceph_mdsc_put_request(req);
+       if (want_parent) {
+-              dout("snapfh_to_parent %llx.%llx\n err=%d\n",
+-                   vino.ino, vino.snap, err);
++              doutc(cl, "%llx.%llx\n err=%d\n", vino.ino, vino.snap, err);
+       } else {
+-              dout("snapfh_to_dentry %llx.%llx parent %llx hash %x err=%d",
+-                    vino.ino, vino.snap, sfh->parent_ino, sfh->hash, err);
++              doutc(cl, "%llx.%llx parent %llx hash %x err=%d", vino.ino,
++                    vino.snap, sfh->parent_ino, sfh->hash, err);
+       }
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+@@ -297,6 +299,7 @@ static struct dentry *ceph_fh_to_dentry(
+                                       struct fid *fid,
+                                       int fh_len, int fh_type)
+ {
++      struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
+       struct ceph_nfs_fh *fh = (void *)fid->raw;
+       if (fh_type == FILEID_BTRFS_WITH_PARENT) {
+@@ -310,7 +313,7 @@ static struct dentry *ceph_fh_to_dentry(
+       if (fh_len < sizeof(*fh) / 4)
+               return NULL;
+-      dout("fh_to_dentry %llx\n", fh->ino);
++      doutc(fsc->client, "%llx\n", fh->ino);
+       return __fh_to_dentry(sb, fh->ino);
+ }
+@@ -363,6 +366,7 @@ static struct dentry *__get_parent(struc
+ static struct dentry *ceph_get_parent(struct dentry *child)
+ {
+       struct inode *inode = d_inode(child);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct dentry *dn;
+       if (ceph_snap(inode) != CEPH_NOSNAP) {
+@@ -402,8 +406,8 @@ static struct dentry *ceph_get_parent(st
+               dn = __get_parent(child->d_sb, child, 0);
+       }
+ out:
+-      dout("get_parent %p ino %llx.%llx err=%ld\n",
+-           child, ceph_vinop(inode), (long)PTR_ERR_OR_ZERO(dn));
++      doutc(cl, "child %p %p %llx.%llx err=%ld\n", child, inode,
++            ceph_vinop(inode), (long)PTR_ERR_OR_ZERO(dn));
+       return dn;
+ }
+@@ -414,6 +418,7 @@ static struct dentry *ceph_fh_to_parent(
+                                       struct fid *fid,
+                                       int fh_len, int fh_type)
+ {
++      struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
+       struct ceph_nfs_confh *cfh = (void *)fid->raw;
+       struct dentry *dentry;
+@@ -427,7 +432,7 @@ static struct dentry *ceph_fh_to_parent(
+       if (fh_len < sizeof(*cfh) / 4)
+               return NULL;
+-      dout("fh_to_parent %llx\n", cfh->parent_ino);
++      doutc(fsc->client, "%llx\n", cfh->parent_ino);
+       dentry = __get_parent(sb, NULL, cfh->ino);
+       if (unlikely(dentry == ERR_PTR(-ENOENT)))
+               dentry = __fh_to_dentry(sb, cfh->parent_ino);
+@@ -526,8 +531,8 @@ out:
+       if (req)
+               ceph_mdsc_put_request(req);
+       kfree(last_name);
+-      dout("get_snap_name %p ino %llx.%llx err=%d\n",
+-           child, ceph_vinop(inode), err);
++      doutc(fsc->client, "child dentry %p %p %llx.%llx err=%d\n", child,
++            inode, ceph_vinop(inode), err);
+       return err;
+ }
+@@ -588,9 +593,9 @@ static int ceph_get_name(struct dentry *
+               ceph_fname_free_buffer(dir, &oname);
+       }
+ out:
+-      dout("get_name %p ino %llx.%llx err %d %s%s\n",
+-                   child, ceph_vinop(inode), err,
+-                   err ? "" : "name ", err ? "" : name);
++      doutc(mdsc->fsc->client, "child dentry %p %p %llx.%llx err %d %s%s\n",
++            child, inode, ceph_vinop(inode), err, err ? "" : "name ",
++            err ? "" : name);
+       ceph_mdsc_put_request(req);
+       return err;
+ }
+--- a/fs/ceph/file.c
++++ b/fs/ceph/file.c
+@@ -19,8 +19,9 @@
+ #include "io.h"
+ #include "metric.h"
+-static __le32 ceph_flags_sys2wire(u32 flags)
++static __le32 ceph_flags_sys2wire(struct ceph_mds_client *mdsc, u32 flags)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       u32 wire_flags = 0;
+       switch (flags & O_ACCMODE) {
+@@ -48,7 +49,7 @@ static __le32 ceph_flags_sys2wire(u32 fl
+ #undef ceph_sys2wire
+       if (flags)
+-              dout("unused open flags: %x\n", flags);
++              doutc(cl, "unused open flags: %x\n", flags);
+       return cpu_to_le32(wire_flags);
+ }
+@@ -189,7 +190,7 @@ prepare_open_request(struct super_block
+       if (IS_ERR(req))
+               goto out;
+       req->r_fmode = ceph_flags_to_mode(flags);
+-      req->r_args.open.flags = ceph_flags_sys2wire(flags);
++      req->r_args.open.flags = ceph_flags_sys2wire(mdsc, flags);
+       req->r_args.open.mode = cpu_to_le32(create_mode);
+ out:
+       return req;
+@@ -201,11 +202,12 @@ static int ceph_init_file_info(struct in
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mount_options *opt =
+               ceph_inode_to_fs_client(&ci->netfs.inode)->mount_options;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_file_info *fi;
+       int ret;
+-      dout("%s %p %p 0%o (%s)\n", __func__, inode, file,
+-                      inode->i_mode, isdir ? "dir" : "regular");
++      doutc(cl, "%p %llx.%llx %p 0%o (%s)\n", inode, ceph_vinop(inode),
++            file, inode->i_mode, isdir ? "dir" : "regular");
+       BUG_ON(inode->i_fop->release != ceph_release);
+       if (isdir) {
+@@ -259,6 +261,7 @@ error:
+  */
+ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int ret = 0;
+       switch (inode->i_mode & S_IFMT) {
+@@ -271,13 +274,13 @@ static int ceph_init_file(struct inode *
+               break;
+       case S_IFLNK:
+-              dout("init_file %p %p 0%o (symlink)\n", inode, file,
+-                   inode->i_mode);
++              doutc(cl, "%p %llx.%llx %p 0%o (symlink)\n", inode,
++                    ceph_vinop(inode), file, inode->i_mode);
+               break;
+       default:
+-              dout("init_file %p %p 0%o (special)\n", inode, file,
+-                   inode->i_mode);
++              doutc(cl, "%p %llx.%llx %p 0%o (special)\n", inode,
++                    ceph_vinop(inode), file, inode->i_mode);
+               /*
+                * we need to drop the open ref now, since we don't
+                * have .release set to ceph_release.
+@@ -296,6 +299,7 @@ static int ceph_init_file(struct inode *
+ int ceph_renew_caps(struct inode *inode, int fmode)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_request *req;
+       int err, flags, wanted;
+@@ -307,8 +311,9 @@ int ceph_renew_caps(struct inode *inode,
+           (!(wanted & CEPH_CAP_ANY_WR) || ci->i_auth_cap)) {
+               int issued = __ceph_caps_issued(ci, NULL);
+               spin_unlock(&ci->i_ceph_lock);
+-              dout("renew caps %p want %s issued %s updating mds_wanted\n",
+-                   inode, ceph_cap_string(wanted), ceph_cap_string(issued));
++              doutc(cl, "%p %llx.%llx want %s issued %s updating mds_wanted\n",
++                    inode, ceph_vinop(inode), ceph_cap_string(wanted),
++                    ceph_cap_string(issued));
+               ceph_check_caps(ci, 0);
+               return 0;
+       }
+@@ -339,7 +344,8 @@ int ceph_renew_caps(struct inode *inode,
+       err = ceph_mdsc_do_request(mdsc, NULL, req);
+       ceph_mdsc_put_request(req);
+ out:
+-      dout("renew caps %p open result=%d\n", inode, err);
++      doutc(cl, "%p %llx.%llx open result=%d\n", inode, ceph_vinop(inode),
++            err);
+       return err < 0 ? err : 0;
+ }
+@@ -353,6 +359,7 @@ int ceph_open(struct inode *inode, struc
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       struct ceph_mds_request *req;
+       struct ceph_file_info *fi = file->private_data;
+@@ -360,7 +367,7 @@ int ceph_open(struct inode *inode, struc
+       int flags, fmode, wanted;
+       if (fi) {
+-              dout("open file %p is already opened\n", file);
++              doutc(cl, "file %p is already opened\n", file);
+               return 0;
+       }
+@@ -374,8 +381,8 @@ int ceph_open(struct inode *inode, struc
+                       return err;
+       }
+-      dout("open inode %p ino %llx.%llx file %p flags %d (%d)\n", inode,
+-           ceph_vinop(inode), file, flags, file->f_flags);
++      doutc(cl, "%p %llx.%llx file %p flags %d (%d)\n", inode,
++            ceph_vinop(inode), file, flags, file->f_flags);
+       fmode = ceph_flags_to_mode(flags);
+       wanted = ceph_caps_for_mode(fmode);
+@@ -399,9 +406,9 @@ int ceph_open(struct inode *inode, struc
+               int mds_wanted = __ceph_caps_mds_wanted(ci, true);
+               int issued = __ceph_caps_issued(ci, NULL);
+-              dout("open %p fmode %d want %s issued %s using existing\n",
+-                   inode, fmode, ceph_cap_string(wanted),
+-                   ceph_cap_string(issued));
++              doutc(cl, "open %p fmode %d want %s issued %s using existing\n",
++                    inode, fmode, ceph_cap_string(wanted),
++                    ceph_cap_string(issued));
+               __ceph_touch_fmode(ci, mdsc, fmode);
+               spin_unlock(&ci->i_ceph_lock);
+@@ -421,7 +428,7 @@ int ceph_open(struct inode *inode, struc
+       spin_unlock(&ci->i_ceph_lock);
+-      dout("open fmode %d wants %s\n", fmode, ceph_cap_string(wanted));
++      doutc(cl, "open fmode %d wants %s\n", fmode, ceph_cap_string(wanted));
+       req = prepare_open_request(inode->i_sb, flags, 0);
+       if (IS_ERR(req)) {
+               err = PTR_ERR(req);
+@@ -435,7 +442,7 @@ int ceph_open(struct inode *inode, struc
+       if (!err)
+               err = ceph_init_file(inode, file, req->r_fmode);
+       ceph_mdsc_put_request(req);
+-      dout("open result=%d on %llx.%llx\n", err, ceph_vinop(inode));
++      doutc(cl, "open result=%d on %llx.%llx\n", err, ceph_vinop(inode));
+ out:
+       return err;
+ }
+@@ -515,6 +522,7 @@ no_async:
+ static void restore_deleg_ino(struct inode *dir, u64 ino)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(dir);
+       struct ceph_inode_info *ci = ceph_inode(dir);
+       struct ceph_mds_session *s = NULL;
+@@ -525,7 +533,8 @@ static void restore_deleg_ino(struct ino
+       if (s) {
+               int err = ceph_restore_deleg_ino(s, ino);
+               if (err)
+-                      pr_warn("ceph: unable to restore delegated ino 0x%llx to session: %d\n",
++                      pr_warn_client(cl,
++                              "unable to restore delegated ino 0x%llx to session: %d\n",
+                               ino, err);
+               ceph_put_mds_session(s);
+       }
+@@ -556,6 +565,7 @@ static void wake_async_create_waiters(st
+ static void ceph_async_create_cb(struct ceph_mds_client *mdsc,
+                                  struct ceph_mds_request *req)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct dentry *dentry = req->r_dentry;
+       struct inode *dinode = d_inode(dentry);
+       struct inode *tinode = req->r_target_inode;
+@@ -576,7 +586,8 @@ static void ceph_async_create_cb(struct
+               char *path = ceph_mdsc_build_path(mdsc, req->r_dentry, &pathlen,
+                                                 &base, 0);
+-              pr_warn("async create failure path=(%llx)%s result=%d!\n",
++              pr_warn_client(cl,
++                      "async create failure path=(%llx)%s result=%d!\n",
+                       base, IS_ERR(path) ? "<<bad>>" : path, result);
+               ceph_mdsc_free_path(path, pathlen);
+@@ -595,14 +606,15 @@ static void ceph_async_create_cb(struct
+               u64 ino = ceph_vino(tinode).ino;
+               if (req->r_deleg_ino != ino)
+-                      pr_warn("%s: inode number mismatch! err=%d deleg_ino=0x%llx target=0x%llx\n",
+-                              __func__, req->r_err, req->r_deleg_ino, ino);
++                      pr_warn_client(cl,
++                              "inode number mismatch! err=%d deleg_ino=0x%llx target=0x%llx\n",
++                              req->r_err, req->r_deleg_ino, ino);
+               mapping_set_error(tinode->i_mapping, result);
+               wake_async_create_waiters(tinode, req->r_session);
+       } else if (!result) {
+-              pr_warn("%s: no req->r_target_inode for 0x%llx\n", __func__,
+-                      req->r_deleg_ino);
++              pr_warn_client(cl, "no req->r_target_inode for 0x%llx\n",
++                             req->r_deleg_ino);
+       }
+ out:
+       ceph_mdsc_release_dir_caps(req);
+@@ -624,6 +636,7 @@ static int ceph_finish_async_create(stru
+       struct timespec64 now;
+       struct ceph_string *pool_ns;
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_vino vino = { .ino = req->r_deleg_ino,
+                                 .snap = CEPH_NOSNAP };
+@@ -682,7 +695,7 @@ static int ceph_finish_async_create(stru
+                             req->r_fmode, NULL);
+       up_read(&mdsc->snap_rwsem);
+       if (ret) {
+-              dout("%s failed to fill inode: %d\n", __func__, ret);
++              doutc(cl, "failed to fill inode: %d\n", ret);
+               ceph_dir_clear_complete(dir);
+               if (!d_unhashed(dentry))
+                       d_drop(dentry);
+@@ -690,8 +703,8 @@ static int ceph_finish_async_create(stru
+       } else {
+               struct dentry *dn;
+-              dout("%s d_adding new inode 0x%llx to 0x%llx/%s\n", __func__,
+-                      vino.ino, ceph_ino(dir), dentry->d_name.name);
++              doutc(cl, "d_adding new inode 0x%llx to 0x%llx/%s\n",
++                    vino.ino, ceph_ino(dir), dentry->d_name.name);
+               ceph_dir_clear_ordered(dir);
+               ceph_init_inode_acls(inode, as_ctx);
+               if (inode->i_state & I_NEW) {
+@@ -729,6 +742,7 @@ int ceph_atomic_open(struct inode *dir,
+                    struct file *file, unsigned flags, umode_t mode)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       struct ceph_mds_request *req;
+       struct inode *new_inode = NULL;
+@@ -738,9 +752,9 @@ int ceph_atomic_open(struct inode *dir,
+       int mask;
+       int err;
+-      dout("atomic_open %p dentry %p '%pd' %s flags %d mode 0%o\n",
+-           dir, dentry, dentry,
+-           d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode);
++      doutc(cl, "%p %llx.%llx dentry %p '%pd' %s flags %d mode 0%o\n",
++            dir, ceph_vinop(dir), dentry, dentry,
++            d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode);
+       if (dentry->d_name.len > NAME_MAX)
+               return -ENAMETOOLONG;
+@@ -878,17 +892,18 @@ retry:
+               goto out_req;
+       if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
+               /* make vfs retry on splice, ENOENT, or symlink */
+-              dout("atomic_open finish_no_open on dn %p\n", dn);
++              doutc(cl, "finish_no_open on dn %p\n", dn);
+               err = finish_no_open(file, dn);
+       } else {
+               if (IS_ENCRYPTED(dir) &&
+                   !fscrypt_has_permitted_context(dir, d_inode(dentry))) {
+-                      pr_warn("Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
++                      pr_warn_client(cl,
++                              "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
+                               ceph_vinop(dir), ceph_vinop(d_inode(dentry)));
+                       goto out_req;
+               }
+-              dout("atomic_open finish_open on dn %p\n", dn);
++              doutc(cl, "finish_open on dn %p\n", dn);
+               if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
+                       struct inode *newino = d_inode(dentry);
+@@ -903,17 +918,19 @@ out_req:
+       iput(new_inode);
+ out_ctx:
+       ceph_release_acl_sec_ctx(&as_ctx);
+-      dout("atomic_open result=%d\n", err);
++      doutc(cl, "result=%d\n", err);
+       return err;
+ }
+ int ceph_release(struct inode *inode, struct file *file)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       if (S_ISDIR(inode->i_mode)) {
+               struct ceph_dir_file_info *dfi = file->private_data;
+-              dout("release inode %p dir file %p\n", inode, file);
++              doutc(cl, "%p %llx.%llx dir file %p\n", inode,
++                    ceph_vinop(inode), file);
+               WARN_ON(!list_empty(&dfi->file_info.rw_contexts));
+               ceph_put_fmode(ci, dfi->file_info.fmode, 1);
+@@ -925,7 +942,8 @@ int ceph_release(struct inode *inode, st
+               kmem_cache_free(ceph_dir_file_cachep, dfi);
+       } else {
+               struct ceph_file_info *fi = file->private_data;
+-              dout("release inode %p regular file %p\n", inode, file);
++              doutc(cl, "%p %llx.%llx regular file %p\n", inode,
++                    ceph_vinop(inode), file);
+               WARN_ON(!list_empty(&fi->rw_contexts));
+               ceph_fscache_unuse_cookie(inode, file->f_mode & FMODE_WRITE);
+@@ -961,6 +979,7 @@ ssize_t __ceph_sync_read(struct inode *i
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_osd_client *osdc = &fsc->client->osdc;
+       ssize_t ret;
+       u64 off = *ki_pos;
+@@ -969,7 +988,8 @@ ssize_t __ceph_sync_read(struct inode *i
+       bool sparse = IS_ENCRYPTED(inode) || ceph_test_mount_opt(fsc, SPARSEREAD);
+       u64 objver = 0;
+-      dout("sync_read on inode %p %llx~%llx\n", inode, *ki_pos, len);
++      doutc(cl, "on inode %p %llx.%llx %llx~%llx\n", inode,
++            ceph_vinop(inode), *ki_pos, len);
+       if (ceph_inode_is_shutdown(inode))
+               return -EIO;
+@@ -1004,8 +1024,8 @@ ssize_t __ceph_sync_read(struct inode *i
+               /* determine new offset/length if encrypted */
+               ceph_fscrypt_adjust_off_and_len(inode, &read_off, &read_len);
+-              dout("sync_read orig %llu~%llu reading %llu~%llu",
+-                   off, len, read_off, read_len);
++              doutc(cl, "orig %llu~%llu reading %llu~%llu", off, len,
++                    read_off, read_len);
+               req = ceph_osdc_new_request(osdc, &ci->i_layout,
+                                       ci->i_vino, read_off, &read_len, 0, 1,
+@@ -1059,8 +1079,8 @@ ssize_t __ceph_sync_read(struct inode *i
+                       objver = req->r_version;
+               i_size = i_size_read(inode);
+-              dout("sync_read %llu~%llu got %zd i_size %llu%s\n",
+-                   off, len, ret, i_size, (more ? " MORE" : ""));
++              doutc(cl, "%llu~%llu got %zd i_size %llu%s\n", off, len,
++                    ret, i_size, (more ? " MORE" : ""));
+               /* Fix it to go to end of extent map */
+               if (sparse && ret >= 0)
+@@ -1106,8 +1126,8 @@ ssize_t __ceph_sync_read(struct inode *i
+                       int zlen = min(len - ret, i_size - off - ret);
+                       int zoff = page_off + ret;
+-                      dout("sync_read zero gap %llu~%llu\n",
+-                              off + ret, off + ret + zlen);
++                      doutc(cl, "zero gap %llu~%llu\n", off + ret,
++                            off + ret + zlen);
+                       ceph_zero_page_vector_range(zoff, zlen, pages);
+                       ret += zlen;
+               }
+@@ -1152,7 +1172,7 @@ ssize_t __ceph_sync_read(struct inode *i
+               if (last_objver)
+                       *last_objver = objver;
+       }
+-      dout("sync_read result %zd retry_op %d\n", ret, *retry_op);
++      doutc(cl, "result %zd retry_op %d\n", ret, *retry_op);
+       return ret;
+ }
+@@ -1161,9 +1181,11 @@ static ssize_t ceph_sync_read(struct kio
+ {
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file_inode(file);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+-      dout("sync_read on file %p %llx~%zx %s\n", file, iocb->ki_pos,
+-           iov_iter_count(to), (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
++      doutc(cl, "on file %p %llx~%zx %s\n", file, iocb->ki_pos,
++            iov_iter_count(to),
++            (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
+       return __ceph_sync_read(inode, &iocb->ki_pos, to, retry_op, NULL);
+ }
+@@ -1191,6 +1213,7 @@ static void ceph_aio_retry_work(struct w
+ static void ceph_aio_complete(struct inode *inode,
+                             struct ceph_aio_request *aio_req)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       int ret;
+@@ -1204,7 +1227,7 @@ static void ceph_aio_complete(struct ino
+       if (!ret)
+               ret = aio_req->total_len;
+-      dout("ceph_aio_complete %p rc %d\n", inode, ret);
++      doutc(cl, "%p %llx.%llx rc %d\n", inode, ceph_vinop(inode), ret);
+       if (ret >= 0 && aio_req->write) {
+               int dirty;
+@@ -1243,11 +1266,13 @@ static void ceph_aio_complete_req(struct
+       struct ceph_client_metric *metric = &ceph_sb_to_mdsc(inode->i_sb)->metric;
+       unsigned int len = osd_data->bvec_pos.iter.bi_size;
+       bool sparse = (op->op == CEPH_OSD_OP_SPARSE_READ);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       BUG_ON(osd_data->type != CEPH_OSD_DATA_TYPE_BVECS);
+       BUG_ON(!osd_data->num_bvecs);
+-      dout("ceph_aio_complete_req %p rc %d bytes %u\n", inode, rc, len);
++      doutc(cl, "req %p inode %p %llx.%llx, rc %d bytes %u\n", req,
++            inode, ceph_vinop(inode), rc, len);
+       if (rc == -EOLDSNAPC) {
+               struct ceph_aio_work *aio_work;
+@@ -1388,6 +1413,7 @@ ceph_direct_read_write(struct kiocb *ioc
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_client_metric *metric = &fsc->mdsc->metric;
+       struct ceph_vino vino;
+       struct ceph_osd_request *req;
+@@ -1406,9 +1432,9 @@ ceph_direct_read_write(struct kiocb *ioc
+       if (write && ceph_snap(file_inode(file)) != CEPH_NOSNAP)
+               return -EROFS;
+-      dout("sync_direct_%s on file %p %lld~%u snapc %p seq %lld\n",
+-           (write ? "write" : "read"), file, pos, (unsigned)count,
+-           snapc, snapc ? snapc->seq : 0);
++      doutc(cl, "sync_direct_%s on file %p %lld~%u snapc %p seq %lld\n",
++            (write ? "write" : "read"), file, pos, (unsigned)count,
++            snapc, snapc ? snapc->seq : 0);
+       if (write) {
+               int ret2;
+@@ -1419,7 +1445,8 @@ ceph_direct_read_write(struct kiocb *ioc
+                                       pos >> PAGE_SHIFT,
+                                       (pos + count - 1) >> PAGE_SHIFT);
+               if (ret2 < 0)
+-                      dout("invalidate_inode_pages2_range returned %d\n", ret2);
++                      doutc(cl, "invalidate_inode_pages2_range returned %d\n",
++                            ret2);
+               flags = /* CEPH_OSD_FLAG_ORDERSNAP | */ CEPH_OSD_FLAG_WRITE;
+       } else {
+@@ -1615,6 +1642,7 @@ ceph_sync_write(struct kiocb *iocb, stru
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_osd_client *osdc = &fsc->client->osdc;
+       struct ceph_osd_request *req;
+       struct page **pages;
+@@ -1629,8 +1657,8 @@ ceph_sync_write(struct kiocb *iocb, stru
+       if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
+               return -EROFS;
+-      dout("sync_write on file %p %lld~%u snapc %p seq %lld\n",
+-           file, pos, (unsigned)count, snapc, snapc->seq);
++      doutc(cl, "on file %p %lld~%u snapc %p seq %lld\n", file, pos,
++            (unsigned)count, snapc, snapc->seq);
+       ret = filemap_write_and_wait_range(inode->i_mapping,
+                                          pos, pos + count - 1);
+@@ -1674,9 +1702,9 @@ ceph_sync_write(struct kiocb *iocb, stru
+               last = (pos + len) != (write_pos + write_len);
+               rmw = first || last;
+-              dout("sync_write ino %llx %lld~%llu adjusted %lld~%llu -- %srmw\n",
+-                   ci->i_vino.ino, pos, len, write_pos, write_len,
+-                   rmw ? "" : "no ");
++              doutc(cl, "ino %llx %lld~%llu adjusted %lld~%llu -- %srmw\n",
++                    ci->i_vino.ino, pos, len, write_pos, write_len,
++                    rmw ? "" : "no ");
+               /*
+                * The data is emplaced into the page as it would be if it were
+@@ -1885,7 +1913,7 @@ ceph_sync_write(struct kiocb *iocb, stru
+                       left -= ret;
+               }
+               if (ret < 0) {
+-                      dout("sync_write write failed with %d\n", ret);
++                      doutc(cl, "write failed with %d\n", ret);
+                       ceph_release_page_vector(pages, num_pages);
+                       break;
+               }
+@@ -1895,7 +1923,7 @@ ceph_sync_write(struct kiocb *iocb, stru
+                                                        write_pos, write_len,
+                                                        GFP_KERNEL);
+                       if (ret < 0) {
+-                              dout("encryption failed with %d\n", ret);
++                              doutc(cl, "encryption failed with %d\n", ret);
+                               ceph_release_page_vector(pages, num_pages);
+                               break;
+                       }
+@@ -1914,7 +1942,7 @@ ceph_sync_write(struct kiocb *iocb, stru
+                       break;
+               }
+-              dout("sync_write write op %lld~%llu\n", write_pos, write_len);
++              doutc(cl, "write op %lld~%llu\n", write_pos, write_len);
+               osd_req_op_extent_osd_data_pages(req, rmw ? 1 : 0, pages, write_len,
+                                                offset_in_page(write_pos), false,
+                                                true);
+@@ -1945,7 +1973,7 @@ ceph_sync_write(struct kiocb *iocb, stru
+                                         req->r_end_latency, len, ret);
+               ceph_osdc_put_request(req);
+               if (ret != 0) {
+-                      dout("sync_write osd write returned %d\n", ret);
++                      doutc(cl, "osd write returned %d\n", ret);
+                       /* Version changed! Must re-do the rmw cycle */
+                       if ((assert_ver && (ret == -ERANGE || ret == -EOVERFLOW)) ||
+                           (!assert_ver && ret == -EEXIST)) {
+@@ -1975,13 +2003,13 @@ ceph_sync_write(struct kiocb *iocb, stru
+                               pos >> PAGE_SHIFT,
+                               (pos + len - 1) >> PAGE_SHIFT);
+               if (ret < 0) {
+-                      dout("invalidate_inode_pages2_range returned %d\n",
+-                           ret);
++                      doutc(cl, "invalidate_inode_pages2_range returned %d\n",
++                            ret);
+                       ret = 0;
+               }
+               pos += len;
+               written += len;
+-              dout("sync_write written %d\n", written);
++              doutc(cl, "written %d\n", written);
+               if (pos > i_size_read(inode)) {
+                       check_caps = ceph_inode_set_size(inode, pos);
+                       if (check_caps)
+@@ -1995,7 +2023,7 @@ ceph_sync_write(struct kiocb *iocb, stru
+               ret = written;
+               iocb->ki_pos = pos;
+       }
+-      dout("sync_write returning %d\n", ret);
++      doutc(cl, "returning %d\n", ret);
+       return ret;
+ }
+@@ -2014,13 +2042,14 @@ static ssize_t ceph_read_iter(struct kio
+       struct inode *inode = file_inode(filp);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       bool direct_lock = iocb->ki_flags & IOCB_DIRECT;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       ssize_t ret;
+       int want = 0, got = 0;
+       int retry_op = 0, read = 0;
+ again:
+-      dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
+-           inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, inode);
++      doutc(cl, "%llu~%u trying to get caps on %p %llx.%llx\n",
++            iocb->ki_pos, (unsigned)len, inode, ceph_vinop(inode));
+       if (ceph_inode_is_shutdown(inode))
+               return -ESTALE;
+@@ -2048,9 +2077,9 @@ again:
+           (iocb->ki_flags & IOCB_DIRECT) ||
+           (fi->flags & CEPH_F_SYNC)) {
+-              dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n",
+-                   inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
+-                   ceph_cap_string(got));
++              doutc(cl, "sync %p %llx.%llx %llu~%u got cap refs on %s\n",
++                    inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
++                    ceph_cap_string(got));
+               if (!ceph_has_inline_data(ci)) {
+                       if (!retry_op &&
+@@ -2068,16 +2097,16 @@ again:
+               }
+       } else {
+               CEPH_DEFINE_RW_CONTEXT(rw_ctx, got);
+-              dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
+-                   inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
+-                   ceph_cap_string(got));
++              doutc(cl, "async %p %llx.%llx %llu~%u got cap refs on %s\n",
++                    inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
++                    ceph_cap_string(got));
+               ceph_add_rw_context(fi, &rw_ctx);
+               ret = generic_file_read_iter(iocb, to);
+               ceph_del_rw_context(fi, &rw_ctx);
+       }
+-      dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
+-           inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);
++      doutc(cl, "%p %llx.%llx dropping cap refs on %s = %d\n",
++            inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);
+       ceph_put_cap_refs(ci, got);
+       if (direct_lock)
+@@ -2137,8 +2166,8 @@ again:
+               /* hit EOF or hole? */
+               if (retry_op == CHECK_EOF && iocb->ki_pos < i_size &&
+                   ret < len) {
+-                      dout("sync_read hit hole, ppos %lld < size %lld"
+-                           ", reading more\n", iocb->ki_pos, i_size);
++                      doutc(cl, "hit hole, ppos %lld < size %lld, reading more\n",
++                            iocb->ki_pos, i_size);
+                       read += ret;
+                       len -= ret;
+@@ -2233,6 +2262,7 @@ static ssize_t ceph_write_iter(struct ki
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_osd_client *osdc = &fsc->client->osdc;
+       struct ceph_cap_flush *prealloc_cf;
+       ssize_t count, written = 0;
+@@ -2300,8 +2330,9 @@ retry_snap:
+       if (err)
+               goto out;
+-      dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n",
+-           inode, ceph_vinop(inode), pos, count, i_size_read(inode));
++      doutc(cl, "%p %llx.%llx %llu~%zd getting caps. i_size %llu\n",
++            inode, ceph_vinop(inode), pos, count,
++            i_size_read(inode));
+       if (!(fi->flags & CEPH_F_SYNC) && !direct_lock)
+               want |= CEPH_CAP_FILE_BUFFER;
+       if (fi->fmode & CEPH_FILE_MODE_LAZY)
+@@ -2317,8 +2348,8 @@ retry_snap:
+       inode_inc_iversion_raw(inode);
+-      dout("aio_write %p %llx.%llx %llu~%zd got cap refs on %s\n",
+-           inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
++      doutc(cl, "%p %llx.%llx %llu~%zd got cap refs on %s\n",
++            inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
+       if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
+           (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC) ||
+@@ -2378,14 +2409,14 @@ retry_snap:
+                       ceph_check_caps(ci, CHECK_CAPS_FLUSH);
+       }
+-      dout("aio_write %p %llx.%llx %llu~%u  dropping cap refs on %s\n",
+-           inode, ceph_vinop(inode), pos, (unsigned)count,
+-           ceph_cap_string(got));
++      doutc(cl, "%p %llx.%llx %llu~%u  dropping cap refs on %s\n",
++            inode, ceph_vinop(inode), pos, (unsigned)count,
++            ceph_cap_string(got));
+       ceph_put_cap_refs(ci, got);
+       if (written == -EOLDSNAPC) {
+-              dout("aio_write %p %llx.%llx %llu~%u" "got EOLDSNAPC, retrying\n",
+-                   inode, ceph_vinop(inode), pos, (unsigned)count);
++              doutc(cl, "%p %llx.%llx %llu~%u" "got EOLDSNAPC, retrying\n",
++                    inode, ceph_vinop(inode), pos, (unsigned)count);
+               goto retry_snap;
+       }
+@@ -2572,14 +2603,15 @@ static long ceph_fallocate(struct file *
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_cap_flush *prealloc_cf;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int want, got = 0;
+       int dirty;
+       int ret = 0;
+       loff_t endoff = 0;
+       loff_t size;
+-      dout("%s %p %llx.%llx mode %x, offset %llu length %llu\n", __func__,
+-           inode, ceph_vinop(inode), mode, offset, length);
++      doutc(cl, "%p %llx.%llx mode %x, offset %llu length %llu\n",
++            inode, ceph_vinop(inode), mode, offset, length);
+       if (mode != (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+               return -EOPNOTSUPP;
+@@ -2708,6 +2740,7 @@ static void put_rd_wr_caps(struct ceph_i
+ static int is_file_size_ok(struct inode *src_inode, struct inode *dst_inode,
+                          loff_t src_off, loff_t dst_off, size_t len)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(src_inode);
+       loff_t size, endoff;
+       size = i_size_read(src_inode);
+@@ -2718,8 +2751,8 @@ static int is_file_size_ok(struct inode
+        * inode.
+        */
+       if (src_off + len > size) {
+-              dout("Copy beyond EOF (%llu + %zu > %llu)\n",
+-                   src_off, len, size);
++              doutc(cl, "Copy beyond EOF (%llu + %zu > %llu)\n", src_off,
++                    len, size);
+               return -EOPNOTSUPP;
+       }
+       size = i_size_read(dst_inode);
+@@ -2795,6 +2828,7 @@ static ssize_t ceph_do_objects_copy(stru
+       u64 src_objnum, src_objoff, dst_objnum, dst_objoff;
+       u32 src_objlen, dst_objlen;
+       u32 object_size = src_ci->i_layout.object_size;
++      struct ceph_client *cl = fsc->client;
+       int ret;
+       src_oloc.pool = src_ci->i_layout.pool_id;
+@@ -2836,9 +2870,10 @@ static ssize_t ceph_do_objects_copy(stru
+               if (ret) {
+                       if (ret == -EOPNOTSUPP) {
+                               fsc->have_copy_from2 = false;
+-                              pr_notice("OSDs don't support copy-from2; disabling copy offload\n");
++                              pr_notice_client(cl,
++                                      "OSDs don't support copy-from2; disabling copy offload\n");
+                       }
+-                      dout("ceph_osdc_copy_from returned %d\n", ret);
++                      doutc(cl, "returned %d\n", ret);
+                       if (!bytes)
+                               bytes = ret;
+                       goto out;
+@@ -2865,6 +2900,7 @@ static ssize_t __ceph_copy_file_range(st
+       struct ceph_inode_info *dst_ci = ceph_inode(dst_inode);
+       struct ceph_cap_flush *prealloc_cf;
+       struct ceph_fs_client *src_fsc = ceph_inode_to_fs_client(src_inode);
++      struct ceph_client *cl = src_fsc->client;
+       loff_t size;
+       ssize_t ret = -EIO, bytes;
+       u64 src_objnum, dst_objnum, src_objoff, dst_objoff;
+@@ -2907,7 +2943,7 @@ static ssize_t __ceph_copy_file_range(st
+           (src_ci->i_layout.stripe_count != 1) ||
+           (dst_ci->i_layout.stripe_count != 1) ||
+           (src_ci->i_layout.object_size != dst_ci->i_layout.object_size)) {
+-              dout("Invalid src/dst files layout\n");
++              doutc(cl, "Invalid src/dst files layout\n");
+               return -EOPNOTSUPP;
+       }
+@@ -2925,12 +2961,12 @@ static ssize_t __ceph_copy_file_range(st
+       /* Start by sync'ing the source and destination files */
+       ret = file_write_and_wait_range(src_file, src_off, (src_off + len));
+       if (ret < 0) {
+-              dout("failed to write src file (%zd)\n", ret);
++              doutc(cl, "failed to write src file (%zd)\n", ret);
+               goto out;
+       }
+       ret = file_write_and_wait_range(dst_file, dst_off, (dst_off + len));
+       if (ret < 0) {
+-              dout("failed to write dst file (%zd)\n", ret);
++              doutc(cl, "failed to write dst file (%zd)\n", ret);
+               goto out;
+       }
+@@ -2942,7 +2978,7 @@ static ssize_t __ceph_copy_file_range(st
+       err = get_rd_wr_caps(src_file, &src_got,
+                            dst_file, (dst_off + len), &dst_got);
+       if (err < 0) {
+-              dout("get_rd_wr_caps returned %d\n", err);
++              doutc(cl, "get_rd_wr_caps returned %d\n", err);
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+@@ -2957,7 +2993,8 @@ static ssize_t __ceph_copy_file_range(st
+                                           dst_off >> PAGE_SHIFT,
+                                           (dst_off + len) >> PAGE_SHIFT);
+       if (ret < 0) {
+-              dout("Failed to invalidate inode pages (%zd)\n", ret);
++              doutc(cl, "Failed to invalidate inode pages (%zd)\n",
++                          ret);
+               ret = 0; /* XXX */
+       }
+       ceph_calc_file_object_mapping(&src_ci->i_layout, src_off,
+@@ -2978,7 +3015,7 @@ static ssize_t __ceph_copy_file_range(st
+        * starting at the src_off
+        */
+       if (src_objoff) {
+-              dout("Initial partial copy of %u bytes\n", src_objlen);
++              doutc(cl, "Initial partial copy of %u bytes\n", src_objlen);
+               /*
+                * we need to temporarily drop all caps as we'll be calling
+@@ -2989,7 +3026,7 @@ static ssize_t __ceph_copy_file_range(st
+                                      &dst_off, src_objlen, flags);
+               /* Abort on short copies or on error */
+               if (ret < (long)src_objlen) {
+-                      dout("Failed partial copy (%zd)\n", ret);
++                      doutc(cl, "Failed partial copy (%zd)\n", ret);
+                       goto out;
+               }
+               len -= ret;
+@@ -3011,7 +3048,7 @@ static ssize_t __ceph_copy_file_range(st
+                       ret = bytes;
+               goto out_caps;
+       }
+-      dout("Copied %zu bytes out of %zu\n", bytes, len);
++      doutc(cl, "Copied %zu bytes out of %zu\n", bytes, len);
+       len -= bytes;
+       ret += bytes;
+@@ -3039,13 +3076,13 @@ out_caps:
+        * there were errors in remote object copies (len >= object_size).
+        */
+       if (len && (len < src_ci->i_layout.object_size)) {
+-              dout("Final partial copy of %zu bytes\n", len);
++              doutc(cl, "Final partial copy of %zu bytes\n", len);
+               bytes = do_splice_direct(src_file, &src_off, dst_file,
+                                        &dst_off, len, flags);
+               if (bytes > 0)
+                       ret += bytes;
+               else
+-                      dout("Failed partial copy (%zd)\n", bytes);
++                      doutc(cl, "Failed partial copy (%zd)\n", bytes);
+       }
+ out:
+--- a/fs/ceph/inode.c
++++ b/fs/ceph/inode.c
+@@ -129,6 +129,8 @@ void ceph_as_ctx_to_req(struct ceph_mds_
+ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino,
+                            struct inode *newino)
+ {
++      struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct inode *inode;
+       if (ceph_vino_is_reserved(vino))
+@@ -145,12 +147,13 @@ struct inode *ceph_get_inode(struct supe
+       }
+       if (!inode) {
+-              dout("No inode found for %llx.%llx\n", vino.ino, vino.snap);
++              doutc(cl, "no inode found for %llx.%llx\n", vino.ino, vino.snap);
+               return ERR_PTR(-ENOMEM);
+       }
+-      dout("get_inode on %llu=%llx.%llx got %p new %d\n", ceph_present_inode(inode),
+-           ceph_vinop(inode), inode, !!(inode->i_state & I_NEW));
++      doutc(cl, "on %llx=%llx.%llx got %p new %d\n",
++            ceph_present_inode(inode), ceph_vinop(inode), inode,
++            !!(inode->i_state & I_NEW));
+       return inode;
+ }
+@@ -159,6 +162,7 @@ struct inode *ceph_get_inode(struct supe
+  */
+ struct inode *ceph_get_snapdir(struct inode *parent)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(parent);
+       struct ceph_vino vino = {
+               .ino = ceph_ino(parent),
+               .snap = CEPH_SNAPDIR,
+@@ -171,14 +175,14 @@ struct inode *ceph_get_snapdir(struct in
+               return inode;
+       if (!S_ISDIR(parent->i_mode)) {
+-              pr_warn_once("bad snapdir parent type (mode=0%o)\n",
+-                           parent->i_mode);
++              pr_warn_once_client(cl, "bad snapdir parent type (mode=0%o)\n",
++                                  parent->i_mode);
+               goto err;
+       }
+       if (!(inode->i_state & I_NEW) && !S_ISDIR(inode->i_mode)) {
+-              pr_warn_once("bad snapdir inode type (mode=0%o)\n",
+-                           inode->i_mode);
++              pr_warn_once_client(cl, "bad snapdir inode type (mode=0%o)\n",
++                                  inode->i_mode);
+               goto err;
+       }
+@@ -203,7 +207,7 @@ struct inode *ceph_get_snapdir(struct in
+                       inode->i_flags |= S_ENCRYPTED;
+                       ci->fscrypt_auth_len = pci->fscrypt_auth_len;
+               } else {
+-                      dout("Failed to alloc snapdir fscrypt_auth\n");
++                      doutc(cl, "Failed to alloc snapdir fscrypt_auth\n");
+                       ret = -ENOMEM;
+                       goto err;
+               }
+@@ -249,6 +253,8 @@ const struct inode_operations ceph_file_
+ static struct ceph_inode_frag *__get_or_create_frag(struct ceph_inode_info *ci,
+                                                   u32 f)
+ {
++      struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct rb_node **p;
+       struct rb_node *parent = NULL;
+       struct ceph_inode_frag *frag;
+@@ -279,8 +285,7 @@ static struct ceph_inode_frag *__get_or_
+       rb_link_node(&frag->node, parent, p);
+       rb_insert_color(&frag->node, &ci->i_fragtree);
+-      dout("get_or_create_frag added %llx.%llx frag %x\n",
+-           ceph_vinop(&ci->netfs.inode), f);
++      doutc(cl, "added %p %llx.%llx frag %x\n", inode, ceph_vinop(inode), f);
+       return frag;
+ }
+@@ -313,6 +318,7 @@ struct ceph_inode_frag *__ceph_find_frag
+ static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
+                             struct ceph_inode_frag *pfrag, int *found)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
+       u32 t = ceph_frag_make(0, 0);
+       struct ceph_inode_frag *frag;
+       unsigned nway, i;
+@@ -336,8 +342,8 @@ static u32 __ceph_choose_frag(struct cep
+               /* choose child */
+               nway = 1 << frag->split_by;
+-              dout("choose_frag(%x) %x splits by %d (%d ways)\n", v, t,
+-                   frag->split_by, nway);
++              doutc(cl, "frag(%x) %x splits by %d (%d ways)\n", v, t,
++                    frag->split_by, nway);
+               for (i = 0; i < nway; i++) {
+                       n = ceph_frag_make_child(t, frag->split_by, i);
+                       if (ceph_frag_contains_value(n, v)) {
+@@ -347,7 +353,7 @@ static u32 __ceph_choose_frag(struct cep
+               }
+               BUG_ON(i == nway);
+       }
+-      dout("choose_frag(%x) = %x\n", v, t);
++      doutc(cl, "frag(%x) = %x\n", v, t);
+       return t;
+ }
+@@ -371,6 +377,7 @@ static int ceph_fill_dirfrag(struct inod
+                            struct ceph_mds_reply_dirfrag *dirinfo)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_frag *frag;
+       u32 id = le32_to_cpu(dirinfo->frag);
+       int mds = le32_to_cpu(dirinfo->auth);
+@@ -395,14 +402,14 @@ static int ceph_fill_dirfrag(struct inod
+                       goto out;
+               if (frag->split_by == 0) {
+                       /* tree leaf, remove */
+-                      dout("fill_dirfrag removed %llx.%llx frag %x"
+-                           " (no ref)\n", ceph_vinop(inode), id);
++                      doutc(cl, "removed %p %llx.%llx frag %x (no ref)\n",
++                            inode, ceph_vinop(inode), id);
+                       rb_erase(&frag->node, &ci->i_fragtree);
+                       kfree(frag);
+               } else {
+                       /* tree branch, keep and clear */
+-                      dout("fill_dirfrag cleared %llx.%llx frag %x"
+-                           " referral\n", ceph_vinop(inode), id);
++                      doutc(cl, "cleared %p %llx.%llx frag %x referral\n",
++                            inode, ceph_vinop(inode), id);
+                       frag->mds = -1;
+                       frag->ndist = 0;
+               }
+@@ -415,8 +422,9 @@ static int ceph_fill_dirfrag(struct inod
+       if (IS_ERR(frag)) {
+               /* this is not the end of the world; we can continue
+                  with bad/inaccurate delegation info */
+-              pr_err("fill_dirfrag ENOMEM on mds ref %llx.%llx fg %x\n",
+-                     ceph_vinop(inode), le32_to_cpu(dirinfo->frag));
++              pr_err_client(cl, "ENOMEM on mds ref %p %llx.%llx fg %x\n",
++                            inode, ceph_vinop(inode),
++                            le32_to_cpu(dirinfo->frag));
+               err = -ENOMEM;
+               goto out;
+       }
+@@ -425,8 +433,8 @@ static int ceph_fill_dirfrag(struct inod
+       frag->ndist = min_t(u32, ndist, CEPH_MAX_DIRFRAG_REP);
+       for (i = 0; i < frag->ndist; i++)
+               frag->dist[i] = le32_to_cpu(dirinfo->dist[i]);
+-      dout("fill_dirfrag %llx.%llx frag %x ndist=%d\n",
+-           ceph_vinop(inode), frag->frag, frag->ndist);
++      doutc(cl, "%p %llx.%llx frag %x ndist=%d\n", inode,
++            ceph_vinop(inode), frag->frag, frag->ndist);
+ out:
+       mutex_unlock(&ci->i_fragtree_mutex);
+@@ -454,6 +462,7 @@ static int ceph_fill_fragtree(struct ino
+                             struct ceph_frag_tree_head *fragtree,
+                             struct ceph_mds_reply_dirfrag *dirinfo)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_inode_frag *frag, *prev_frag = NULL;
+       struct rb_node *rb_node;
+@@ -489,15 +498,15 @@ static int ceph_fill_fragtree(struct ino
+                    frag_tree_split_cmp, NULL);
+       }
+-      dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode));
++      doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
+       rb_node = rb_first(&ci->i_fragtree);
+       for (i = 0; i < nsplits; i++) {
+               id = le32_to_cpu(fragtree->splits[i].frag);
+               split_by = le32_to_cpu(fragtree->splits[i].by);
+               if (split_by == 0 || ceph_frag_bits(id) + split_by > 24) {
+-                      pr_err("fill_fragtree %llx.%llx invalid split %d/%u, "
+-                             "frag %x split by %d\n", ceph_vinop(inode),
+-                             i, nsplits, id, split_by);
++                      pr_err_client(cl, "%p %llx.%llx invalid split %d/%u, "
++                             "frag %x split by %d\n", inode,
++                             ceph_vinop(inode), i, nsplits, id, split_by);
+                       continue;
+               }
+               frag = NULL;
+@@ -529,7 +538,7 @@ static int ceph_fill_fragtree(struct ino
+               if (frag->split_by == 0)
+                       ci->i_fragtree_nsplits++;
+               frag->split_by = split_by;
+-              dout(" frag %x split by %d\n", frag->frag, frag->split_by);
++              doutc(cl, " frag %x split by %d\n", frag->frag, frag->split_by);
+               prev_frag = frag;
+       }
+       while (rb_node) {
+@@ -554,6 +563,7 @@ out_unlock:
+  */
+ struct inode *ceph_alloc_inode(struct super_block *sb)
+ {
++      struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
+       struct ceph_inode_info *ci;
+       int i;
+@@ -561,7 +571,7 @@ struct inode *ceph_alloc_inode(struct su
+       if (!ci)
+               return NULL;
+-      dout("alloc_inode %p\n", &ci->netfs.inode);
++      doutc(fsc->client, "%p\n", &ci->netfs.inode);
+       /* Set parameters for the netfs library */
+       netfs_inode_init(&ci->netfs, &ceph_netfs_ops);
+@@ -675,10 +685,11 @@ void ceph_evict_inode(struct inode *inod
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_frag *frag;
+       struct rb_node *n;
+-      dout("evict_inode %p ino %llx.%llx\n", inode, ceph_vinop(inode));
++      doutc(cl, "%p ino %llx.%llx\n", inode, ceph_vinop(inode));
+       percpu_counter_dec(&mdsc->metric.total_inodes);
+@@ -701,8 +712,8 @@ void ceph_evict_inode(struct inode *inod
+        */
+       if (ci->i_snap_realm) {
+               if (ceph_snap(inode) == CEPH_NOSNAP) {
+-                      dout(" dropping residual ref to snap realm %p\n",
+-                           ci->i_snap_realm);
++                      doutc(cl, " dropping residual ref to snap realm %p\n",
++                            ci->i_snap_realm);
+                       ceph_change_snap_realm(inode, NULL);
+               } else {
+                       ceph_put_snapid_map(mdsc, ci->i_snapid_map);
+@@ -743,15 +754,16 @@ static inline blkcnt_t calc_inode_blocks
+ int ceph_fill_file_size(struct inode *inode, int issued,
+                       u32 truncate_seq, u64 truncate_size, u64 size)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       int queue_trunc = 0;
+       loff_t isize = i_size_read(inode);
+       if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 ||
+           (truncate_seq == ci->i_truncate_seq && size > isize)) {
+-              dout("size %lld -> %llu\n", isize, size);
++              doutc(cl, "size %lld -> %llu\n", isize, size);
+               if (size > 0 && S_ISDIR(inode->i_mode)) {
+-                      pr_err("fill_file_size non-zero size for directory\n");
++                      pr_err_client(cl, "non-zero size for directory\n");
+                       size = 0;
+               }
+               i_size_write(inode, size);
+@@ -764,8 +776,8 @@ int ceph_fill_file_size(struct inode *in
+                       ceph_fscache_update(inode);
+               ci->i_reported_size = size;
+               if (truncate_seq != ci->i_truncate_seq) {
+-                      dout("%s truncate_seq %u -> %u\n", __func__,
+-                           ci->i_truncate_seq, truncate_seq);
++                      doutc(cl, "truncate_seq %u -> %u\n",
++                            ci->i_truncate_seq, truncate_seq);
+                       ci->i_truncate_seq = truncate_seq;
+                       /* the MDS should have revoked these caps */
+@@ -794,14 +806,15 @@ int ceph_fill_file_size(struct inode *in
+        * anyway.
+        */
+       if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) >= 0) {
+-              dout("%s truncate_size %lld -> %llu, encrypted %d\n", __func__,
+-                   ci->i_truncate_size, truncate_size, !!IS_ENCRYPTED(inode));
++              doutc(cl, "truncate_size %lld -> %llu, encrypted %d\n",
++                    ci->i_truncate_size, truncate_size,
++                    !!IS_ENCRYPTED(inode));
+               ci->i_truncate_size = truncate_size;
+               if (IS_ENCRYPTED(inode)) {
+-                      dout("%s truncate_pagecache_size %lld -> %llu\n",
+-                           __func__, ci->i_truncate_pagecache_size, size);
++                      doutc(cl, "truncate_pagecache_size %lld -> %llu\n",
++                            ci->i_truncate_pagecache_size, size);
+                       ci->i_truncate_pagecache_size = size;
+               } else {
+                       ci->i_truncate_pagecache_size = truncate_size;
+@@ -814,6 +827,7 @@ void ceph_fill_file_time(struct inode *i
+                        u64 time_warp_seq, struct timespec64 *ctime,
+                        struct timespec64 *mtime, struct timespec64 *atime)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct timespec64 ictime = inode_get_ctime(inode);
+       int warn = 0;
+@@ -825,7 +839,7 @@ void ceph_fill_file_time(struct inode *i
+                     CEPH_CAP_XATTR_EXCL)) {
+               if (ci->i_version == 0 ||
+                   timespec64_compare(ctime, &ictime) > 0) {
+-                      dout("ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
++                      doutc(cl, "ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
+                            ictime.tv_sec, ictime.tv_nsec,
+                            ctime->tv_sec, ctime->tv_nsec);
+                       inode_set_ctime_to_ts(inode, *ctime);
+@@ -833,11 +847,10 @@ void ceph_fill_file_time(struct inode *i
+               if (ci->i_version == 0 ||
+                   ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
+                       /* the MDS did a utimes() */
+-                      dout("mtime %lld.%09ld -> %lld.%09ld "
+-                           "tw %d -> %d\n",
+-                           inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+-                           mtime->tv_sec, mtime->tv_nsec,
+-                           ci->i_time_warp_seq, (int)time_warp_seq);
++                      doutc(cl, "mtime %lld.%09ld -> %lld.%09ld tw %d -> %d\n",
++                            inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
++                            mtime->tv_sec, mtime->tv_nsec,
++                            ci->i_time_warp_seq, (int)time_warp_seq);
+                       inode->i_mtime = *mtime;
+                       inode->i_atime = *atime;
+@@ -845,17 +858,17 @@ void ceph_fill_file_time(struct inode *i
+               } else if (time_warp_seq == ci->i_time_warp_seq) {
+                       /* nobody did utimes(); take the max */
+                       if (timespec64_compare(mtime, &inode->i_mtime) > 0) {
+-                              dout("mtime %lld.%09ld -> %lld.%09ld inc\n",
+-                                   inode->i_mtime.tv_sec,
+-                                   inode->i_mtime.tv_nsec,
+-                                   mtime->tv_sec, mtime->tv_nsec);
++                              doutc(cl, "mtime %lld.%09ld -> %lld.%09ld inc\n",
++                                    inode->i_mtime.tv_sec,
++                                    inode->i_mtime.tv_nsec,
++                                    mtime->tv_sec, mtime->tv_nsec);
+                               inode->i_mtime = *mtime;
+                       }
+                       if (timespec64_compare(atime, &inode->i_atime) > 0) {
+-                              dout("atime %lld.%09ld -> %lld.%09ld inc\n",
+-                                   inode->i_atime.tv_sec,
+-                                   inode->i_atime.tv_nsec,
+-                                   atime->tv_sec, atime->tv_nsec);
++                              doutc(cl, "atime %lld.%09ld -> %lld.%09ld inc\n",
++                                    inode->i_atime.tv_sec,
++                                    inode->i_atime.tv_nsec,
++                                    atime->tv_sec, atime->tv_nsec);
+                               inode->i_atime = *atime;
+                       }
+               } else if (issued & CEPH_CAP_FILE_EXCL) {
+@@ -875,13 +888,16 @@ void ceph_fill_file_time(struct inode *i
+               }
+       }
+       if (warn) /* time_warp_seq shouldn't go backwards */
+-              dout("%p mds time_warp_seq %llu < %u\n",
+-                   inode, time_warp_seq, ci->i_time_warp_seq);
++              doutc(cl, "%p mds time_warp_seq %llu < %u\n", inode,
++                    time_warp_seq, ci->i_time_warp_seq);
+ }
+ #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
+-static int decode_encrypted_symlink(const char *encsym, int enclen, u8 **decsym)
++static int decode_encrypted_symlink(struct ceph_mds_client *mdsc,
++                                  const char *encsym,
++                                  int enclen, u8 **decsym)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int declen;
+       u8 *sym;
+@@ -891,8 +907,9 @@ static int decode_encrypted_symlink(cons
+       declen = ceph_base64_decode(encsym, enclen, sym);
+       if (declen < 0) {
+-              pr_err("%s: can't decode symlink (%d). Content: %.*s\n",
+-                     __func__, declen, enclen, encsym);
++              pr_err_client(cl,
++                      "can't decode symlink (%d). Content: %.*s\n",
++                      declen, enclen, encsym);
+               kfree(sym);
+               return -EIO;
+       }
+@@ -901,7 +918,9 @@ static int decode_encrypted_symlink(cons
+       return declen;
+ }
+ #else
+-static int decode_encrypted_symlink(const char *encsym, int symlen, u8 **decsym)
++static int decode_encrypted_symlink(struct ceph_mds_client *mdsc,
++                                  const char *encsym,
++                                  int symlen, u8 **decsym)
+ {
+       return -EOPNOTSUPP;
+ }
+@@ -918,6 +937,7 @@ int ceph_fill_inode(struct inode *inode,
+                   struct ceph_cap_reservation *caps_reservation)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_reply_inode *info = iinfo->in;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       int issued, new_issued, info_caps;
+@@ -936,25 +956,26 @@ int ceph_fill_inode(struct inode *inode,
+       lockdep_assert_held(&mdsc->snap_rwsem);
+-      dout("%s %p ino %llx.%llx v %llu had %llu\n", __func__,
+-           inode, ceph_vinop(inode), le64_to_cpu(info->version),
+-           ci->i_version);
++      doutc(cl, "%p ino %llx.%llx v %llu had %llu\n", inode, ceph_vinop(inode),
++            le64_to_cpu(info->version), ci->i_version);
+       /* Once I_NEW is cleared, we can't change type or dev numbers */
+       if (inode->i_state & I_NEW) {
+               inode->i_mode = mode;
+       } else {
+               if (inode_wrong_type(inode, mode)) {
+-                      pr_warn_once("inode type changed! (ino %llx.%llx is 0%o, mds says 0%o)\n",
+-                                   ceph_vinop(inode), inode->i_mode, mode);
++                      pr_warn_once_client(cl,
++                              "inode type changed! (ino %llx.%llx is 0%o, mds says 0%o)\n",
++                              ceph_vinop(inode), inode->i_mode, mode);
+                       return -ESTALE;
+               }
+               if ((S_ISCHR(mode) || S_ISBLK(mode)) && inode->i_rdev != rdev) {
+-                      pr_warn_once("dev inode rdev changed! (ino %llx.%llx is %u:%u, mds says %u:%u)\n",
+-                                   ceph_vinop(inode), MAJOR(inode->i_rdev),
+-                                   MINOR(inode->i_rdev), MAJOR(rdev),
+-                                   MINOR(rdev));
++                      pr_warn_once_client(cl,
++                              "dev inode rdev changed! (ino %llx.%llx is %u:%u, mds says %u:%u)\n",
++                              ceph_vinop(inode), MAJOR(inode->i_rdev),
++                              MINOR(inode->i_rdev), MAJOR(rdev),
++                              MINOR(rdev));
+                       return -ESTALE;
+               }
+       }
+@@ -976,8 +997,8 @@ int ceph_fill_inode(struct inode *inode,
+       if (iinfo->xattr_len > 4) {
+               xattr_blob = ceph_buffer_new(iinfo->xattr_len, GFP_NOFS);
+               if (!xattr_blob)
+-                      pr_err("%s ENOMEM xattr blob %d bytes\n", __func__,
+-                             iinfo->xattr_len);
++                      pr_err_client(cl, "ENOMEM xattr blob %d bytes\n",
++                                    iinfo->xattr_len);
+       }
+       if (iinfo->pool_ns_len > 0)
+@@ -1031,9 +1052,10 @@ int ceph_fill_inode(struct inode *inode,
+               inode->i_mode = mode;
+               inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(info->uid));
+               inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(info->gid));
+-              dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
+-                   from_kuid(&init_user_ns, inode->i_uid),
+-                   from_kgid(&init_user_ns, inode->i_gid));
++              doutc(cl, "%p %llx.%llx mode 0%o uid.gid %d.%d\n", inode,
++                    ceph_vinop(inode), inode->i_mode,
++                    from_kuid(&init_user_ns, inode->i_uid),
++                    from_kgid(&init_user_ns, inode->i_gid));
+               ceph_decode_timespec64(&ci->i_btime, &iinfo->btime);
+               ceph_decode_timespec64(&ci->i_snap_btime, &iinfo->snap_btime);
+       }
+@@ -1089,7 +1111,8 @@ int ceph_fill_inode(struct inode *inode,
+                       if (size == round_up(fsize, CEPH_FSCRYPT_BLOCK_SIZE)) {
+                               size = fsize;
+                       } else {
+-                              pr_warn("fscrypt size mismatch: size=%llu fscrypt_file=%llu, discarding fscrypt_file size.\n",
++                              pr_warn_client(cl,
++                                      "fscrypt size mismatch: size=%llu fscrypt_file=%llu, discarding fscrypt_file size.\n",
+                                       info->size, size);
+                       }
+               }
+@@ -1101,8 +1124,8 @@ int ceph_fill_inode(struct inode *inode,
+               /* only update max_size on auth cap */
+               if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) &&
+                   ci->i_max_size != le64_to_cpu(info->max_size)) {
+-                      dout("max_size %lld -> %llu\n", ci->i_max_size,
+-                                      le64_to_cpu(info->max_size));
++                      doutc(cl, "max_size %lld -> %llu\n",
++                          ci->i_max_size, le64_to_cpu(info->max_size));
+                       ci->i_max_size = le64_to_cpu(info->max_size);
+               }
+       }
+@@ -1165,15 +1188,17 @@ int ceph_fill_inode(struct inode *inode,
+                       if (IS_ENCRYPTED(inode)) {
+                               if (symlen != i_size_read(inode))
+-                                      pr_err("%s %llx.%llx BAD symlink size %lld\n",
+-                                              __func__, ceph_vinop(inode),
++                                      pr_err_client(cl,
++                                              "%p %llx.%llx BAD symlink size %lld\n",
++                                              inode, ceph_vinop(inode),
+                                               i_size_read(inode));
+-                              err = decode_encrypted_symlink(iinfo->symlink,
++                              err = decode_encrypted_symlink(mdsc, iinfo->symlink,
+                                                              symlen, (u8 **)&sym);
+                               if (err < 0) {
+-                                      pr_err("%s decoding encrypted symlink failed: %d\n",
+-                                              __func__, err);
++                                      pr_err_client(cl,
++                                              "decoding encrypted symlink failed: %d\n",
++                                              err);
+                                       goto out;
+                               }
+                               symlen = err;
+@@ -1181,8 +1206,9 @@ int ceph_fill_inode(struct inode *inode,
+                               inode->i_blocks = calc_inode_blocks(symlen);
+                       } else {
+                               if (symlen != i_size_read(inode)) {
+-                                      pr_err("%s %llx.%llx BAD symlink size %lld\n",
+-                                              __func__, ceph_vinop(inode),
++                                      pr_err_client(cl,
++                                              "%p %llx.%llx BAD symlink size %lld\n",
++                                              inode, ceph_vinop(inode),
+                                               i_size_read(inode));
+                                       i_size_write(inode, symlen);
+                                       inode->i_blocks = calc_inode_blocks(symlen);
+@@ -1217,8 +1243,8 @@ int ceph_fill_inode(struct inode *inode,
+               inode->i_fop = &ceph_dir_fops;
+               break;
+       default:
+-              pr_err("%s %llx.%llx BAD mode 0%o\n", __func__,
+-                     ceph_vinop(inode), inode->i_mode);
++              pr_err_client(cl, "%p %llx.%llx BAD mode 0%o\n", inode,
++                            ceph_vinop(inode), inode->i_mode);
+       }
+       /* were we issued a capability? */
+@@ -1239,7 +1265,8 @@ int ceph_fill_inode(struct inode *inode,
+                           (info_caps & CEPH_CAP_FILE_SHARED) &&
+                           (issued & CEPH_CAP_FILE_EXCL) == 0 &&
+                           !__ceph_dir_is_complete(ci)) {
+-                              dout(" marking %p complete (empty)\n", inode);
++                              doutc(cl, " marking %p complete (empty)\n",
++                                    inode);
+                               i_size_write(inode, 0);
+                               __ceph_dir_set_complete(ci,
+                                       atomic64_read(&ci->i_release_count),
+@@ -1248,8 +1275,8 @@ int ceph_fill_inode(struct inode *inode,
+                       wake = true;
+               } else {
+-                      dout(" %p got snap_caps %s\n", inode,
+-                           ceph_cap_string(info_caps));
++                      doutc(cl, " %p got snap_caps %s\n", inode,
++                            ceph_cap_string(info_caps));
+                       ci->i_snap_caps |= info_caps;
+               }
+       }
+@@ -1265,8 +1292,8 @@ int ceph_fill_inode(struct inode *inode,
+       if (cap_fmode >= 0) {
+               if (!info_caps)
+-                      pr_warn("mds issued no caps on %llx.%llx\n",
+-                              ceph_vinop(inode));
++                      pr_warn_client(cl, "mds issued no caps on %llx.%llx\n",
++                                     ceph_vinop(inode));
+               __ceph_touch_fmode(ci, mdsc, cap_fmode);
+       }
+@@ -1312,14 +1339,14 @@ static void __update_dentry_lease(struct
+                                 unsigned long from_time,
+                                 struct ceph_mds_session **old_lease_session)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(dir);
+       struct ceph_dentry_info *di = ceph_dentry(dentry);
+       unsigned mask = le16_to_cpu(lease->mask);
+       long unsigned duration = le32_to_cpu(lease->duration_ms);
+       long unsigned ttl = from_time + (duration * HZ) / 1000;
+       long unsigned half_ttl = from_time + (duration * HZ / 2) / 1000;
+-      dout("update_dentry_lease %p duration %lu ms ttl %lu\n",
+-           dentry, duration, ttl);
++      doutc(cl, "%p duration %lu ms ttl %lu\n", dentry, duration, ttl);
+       /* only track leases on regular dentries */
+       if (ceph_snap(dir) != CEPH_NOSNAP)
+@@ -1420,6 +1447,7 @@ out_unlock:
+  */
+ static int splice_dentry(struct dentry **pdn, struct inode *in)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(in);
+       struct dentry *dn = *pdn;
+       struct dentry *realdn;
+@@ -1451,23 +1479,21 @@ static int splice_dentry(struct dentry *
+               d_drop(dn);
+       realdn = d_splice_alias(in, dn);
+       if (IS_ERR(realdn)) {
+-              pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n",
+-                     PTR_ERR(realdn), dn, in, ceph_vinop(in));
++              pr_err_client(cl, "error %ld %p inode %p ino %llx.%llx\n",
++                            PTR_ERR(realdn), dn, in, ceph_vinop(in));
+               return PTR_ERR(realdn);
+       }
+       if (realdn) {
+-              dout("dn %p (%d) spliced with %p (%d) "
+-                   "inode %p ino %llx.%llx\n",
+-                   dn, d_count(dn),
+-                   realdn, d_count(realdn),
+-                   d_inode(realdn), ceph_vinop(d_inode(realdn)));
++              doutc(cl, "dn %p (%d) spliced with %p (%d) inode %p ino %llx.%llx\n",
++                    dn, d_count(dn), realdn, d_count(realdn),
++                    d_inode(realdn), ceph_vinop(d_inode(realdn)));
+               dput(dn);
+               *pdn = realdn;
+       } else {
+               BUG_ON(!ceph_dentry(dn));
+-              dout("dn %p attached to %p ino %llx.%llx\n",
+-                   dn, d_inode(dn), ceph_vinop(d_inode(dn)));
++              doutc(cl, "dn %p attached to %p ino %llx.%llx\n", dn,
++                    d_inode(dn), ceph_vinop(d_inode(dn)));
+       }
+       return 0;
+ }
+@@ -1490,13 +1516,14 @@ int ceph_fill_trace(struct super_block *
+       struct inode *in = NULL;
+       struct ceph_vino tvino, dvino;
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
++      struct ceph_client *cl = fsc->client;
+       int err = 0;
+-      dout("fill_trace %p is_dentry %d is_target %d\n", req,
+-           rinfo->head->is_dentry, rinfo->head->is_target);
++      doutc(cl, "%p is_dentry %d is_target %d\n", req,
++            rinfo->head->is_dentry, rinfo->head->is_target);
+       if (!rinfo->head->is_target && !rinfo->head->is_dentry) {
+-              dout("fill_trace reply is empty!\n");
++              doutc(cl, "reply is empty!\n");
+               if (rinfo->head->result == 0 && req->r_parent)
+                       ceph_invalidate_dir_request(req);
+               return 0;
+@@ -1553,13 +1580,13 @@ int ceph_fill_trace(struct super_block *
+                       tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
+ retry_lookup:
+                       dn = d_lookup(parent, &dname);
+-                      dout("d_lookup on parent=%p name=%.*s got %p\n",
+-                           parent, dname.len, dname.name, dn);
++                      doutc(cl, "d_lookup on parent=%p name=%.*s got %p\n",
++                            parent, dname.len, dname.name, dn);
+                       if (!dn) {
+                               dn = d_alloc(parent, &dname);
+-                              dout("d_alloc %p '%.*s' = %p\n", parent,
+-                                   dname.len, dname.name, dn);
++                              doutc(cl, "d_alloc %p '%.*s' = %p\n", parent,
++                                    dname.len, dname.name, dn);
+                               if (!dn) {
+                                       dput(parent);
+                                       ceph_fname_free_buffer(dir, &oname);
+@@ -1575,8 +1602,8 @@ retry_lookup:
+                       } else if (d_really_is_positive(dn) &&
+                                  (ceph_ino(d_inode(dn)) != tvino.ino ||
+                                   ceph_snap(d_inode(dn)) != tvino.snap)) {
+-                              dout(" dn %p points to wrong inode %p\n",
+-                                   dn, d_inode(dn));
++                              doutc(cl, " dn %p points to wrong inode %p\n",
++                                    dn, d_inode(dn));
+                               ceph_dir_clear_ordered(dir);
+                               d_delete(dn);
+                               dput(dn);
+@@ -1601,8 +1628,8 @@ retry_lookup:
+                                rinfo->head->result == 0) ?  req->r_fmode : -1,
+                               &req->r_caps_reservation);
+               if (err < 0) {
+-                      pr_err("ceph_fill_inode badness %p %llx.%llx\n",
+-                              in, ceph_vinop(in));
++                      pr_err_client(cl, "badness %p %llx.%llx\n", in,
++                                    ceph_vinop(in));
+                       req->r_target_inode = NULL;
+                       if (in->i_state & I_NEW)
+                               discard_new_inode(in);
+@@ -1652,36 +1679,32 @@ retry_lookup:
+               have_lease = have_dir_cap ||
+                       le32_to_cpu(rinfo->dlease->duration_ms);
+               if (!have_lease)
+-                      dout("fill_trace  no dentry lease or dir cap\n");
++                      doutc(cl, "no dentry lease or dir cap\n");
+               /* rename? */
+               if (req->r_old_dentry && req->r_op == CEPH_MDS_OP_RENAME) {
+                       struct inode *olddir = req->r_old_dentry_dir;
+                       BUG_ON(!olddir);
+-                      dout(" src %p '%pd' dst %p '%pd'\n",
+-                           req->r_old_dentry,
+-                           req->r_old_dentry,
+-                           dn, dn);
+-                      dout("fill_trace doing d_move %p -> %p\n",
+-                           req->r_old_dentry, dn);
++                      doutc(cl, " src %p '%pd' dst %p '%pd'\n",
++                            req->r_old_dentry, req->r_old_dentry, dn, dn);
++                      doutc(cl, "doing d_move %p -> %p\n", req->r_old_dentry, dn);
+                       /* d_move screws up sibling dentries' offsets */
+                       ceph_dir_clear_ordered(dir);
+                       ceph_dir_clear_ordered(olddir);
+                       d_move(req->r_old_dentry, dn);
+-                      dout(" src %p '%pd' dst %p '%pd'\n",
+-                           req->r_old_dentry,
+-                           req->r_old_dentry,
+-                           dn, dn);
++                      doutc(cl, " src %p '%pd' dst %p '%pd'\n",
++                            req->r_old_dentry, req->r_old_dentry, dn, dn);
+                       /* ensure target dentry is invalidated, despite
+                          rehashing bug in vfs_rename_dir */
+                       ceph_invalidate_dentry_lease(dn);
+-                      dout("dn %p gets new offset %lld\n", req->r_old_dentry,
+-                           ceph_dentry(req->r_old_dentry)->offset);
++                      doutc(cl, "dn %p gets new offset %lld\n",
++                            req->r_old_dentry,
++                            ceph_dentry(req->r_old_dentry)->offset);
+                       /* swap r_dentry and r_old_dentry in case that
+                        * splice_dentry() gets called later. This is safe
+@@ -1693,9 +1716,9 @@ retry_lookup:
+               /* null dentry? */
+               if (!rinfo->head->is_target) {
+-                      dout("fill_trace null dentry\n");
++                      doutc(cl, "null dentry\n");
+                       if (d_really_is_positive(dn)) {
+-                              dout("d_delete %p\n", dn);
++                              doutc(cl, "d_delete %p\n", dn);
+                               ceph_dir_clear_ordered(dir);
+                               d_delete(dn);
+                       } else if (have_lease) {
+@@ -1719,9 +1742,9 @@ retry_lookup:
+                               goto done;
+                       dn = req->r_dentry;  /* may have spliced */
+               } else if (d_really_is_positive(dn) && d_inode(dn) != in) {
+-                      dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
+-                           dn, d_inode(dn), ceph_vinop(d_inode(dn)),
+-                           ceph_vinop(in));
++                      doutc(cl, " %p links to %p %llx.%llx, not %llx.%llx\n",
++                            dn, d_inode(dn), ceph_vinop(d_inode(dn)),
++                            ceph_vinop(in));
+                       d_invalidate(dn);
+                       have_lease = false;
+               }
+@@ -1731,7 +1754,7 @@ retry_lookup:
+                                           rinfo->dlease, session,
+                                           req->r_request_started);
+               }
+-              dout(" final dn %p\n", dn);
++              doutc(cl, " final dn %p\n", dn);
+       } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
+                   req->r_op == CEPH_MDS_OP_MKSNAP) &&
+                  test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags) &&
+@@ -1742,7 +1765,8 @@ retry_lookup:
+               BUG_ON(!dir);
+               BUG_ON(ceph_snap(dir) != CEPH_SNAPDIR);
+               BUG_ON(!req->r_dentry);
+-              dout(" linking snapped dir %p to dn %p\n", in, req->r_dentry);
++              doutc(cl, " linking snapped dir %p to dn %p\n", in,
++                    req->r_dentry);
+               ceph_dir_clear_ordered(dir);
+               ihold(in);
+               err = splice_dentry(&req->r_dentry, in);
+@@ -1764,7 +1788,7 @@ retry_lookup:
+                                           &dvino, ptvino);
+       }
+ done:
+-      dout("fill_trace done err=%d\n", err);
++      doutc(cl, "done err=%d\n", err);
+       return err;
+ }
+@@ -1775,6 +1799,7 @@ static int readdir_prepopulate_inodes_on
+                                          struct ceph_mds_session *session)
+ {
+       struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
++      struct ceph_client *cl = session->s_mdsc->fsc->client;
+       int i, err = 0;
+       for (i = 0; i < rinfo->dir_nr; i++) {
+@@ -1789,14 +1814,14 @@ static int readdir_prepopulate_inodes_on
+               in = ceph_get_inode(req->r_dentry->d_sb, vino, NULL);
+               if (IS_ERR(in)) {
+                       err = PTR_ERR(in);
+-                      dout("new_inode badness got %d\n", err);
++                      doutc(cl, "badness got %d\n", err);
+                       continue;
+               }
+               rc = ceph_fill_inode(in, NULL, &rde->inode, NULL, session,
+                                    -1, &req->r_caps_reservation);
+               if (rc < 0) {
+-                      pr_err("ceph_fill_inode badness on %p got %d\n",
+-                             in, rc);
++                      pr_err_client(cl, "inode badness on %p got %d\n", in,
++                                    rc);
+                       err = rc;
+                       if (in->i_state & I_NEW) {
+                               ihold(in);
+@@ -1825,6 +1850,7 @@ static int fill_readdir_cache(struct ino
+                             struct ceph_readdir_cache_control *ctl,
+                             struct ceph_mds_request *req)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(dir);
+       struct ceph_inode_info *ci = ceph_inode(dir);
+       unsigned nsize = PAGE_SIZE / sizeof(struct dentry*);
+       unsigned idx = ctl->index % nsize;
+@@ -1850,11 +1876,11 @@ static int fill_readdir_cache(struct ino
+       if (req->r_dir_release_cnt == atomic64_read(&ci->i_release_count) &&
+           req->r_dir_ordered_cnt == atomic64_read(&ci->i_ordered_count)) {
+-              dout("readdir cache dn %p idx %d\n", dn, ctl->index);
++              doutc(cl, "dn %p idx %d\n", dn, ctl->index);
+               ctl->dentries[idx] = dn;
+               ctl->index++;
+       } else {
+-              dout("disable readdir cache\n");
++              doutc(cl, "disable readdir cache\n");
+               ctl->index = -1;
+       }
+       return 0;
+@@ -1867,6 +1893,7 @@ int ceph_readdir_prepopulate(struct ceph
+       struct inode *inode = d_inode(parent);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
++      struct ceph_client *cl = session->s_mdsc->fsc->client;
+       struct qstr dname;
+       struct dentry *dn;
+       struct inode *in;
+@@ -1894,19 +1921,18 @@ int ceph_readdir_prepopulate(struct ceph
+       if (rinfo->dir_dir &&
+           le32_to_cpu(rinfo->dir_dir->frag) != frag) {
+-              dout("readdir_prepopulate got new frag %x -> %x\n",
+-                   frag, le32_to_cpu(rinfo->dir_dir->frag));
++              doutc(cl, "got new frag %x -> %x\n", frag,
++                          le32_to_cpu(rinfo->dir_dir->frag));
+               frag = le32_to_cpu(rinfo->dir_dir->frag);
+               if (!rinfo->hash_order)
+                       req->r_readdir_offset = 2;
+       }
+       if (le32_to_cpu(rinfo->head->op) == CEPH_MDS_OP_LSSNAP) {
+-              dout("readdir_prepopulate %d items under SNAPDIR dn %p\n",
+-                   rinfo->dir_nr, parent);
++              doutc(cl, "%d items under SNAPDIR dn %p\n",
++                    rinfo->dir_nr, parent);
+       } else {
+-              dout("readdir_prepopulate %d items under dn %p\n",
+-                   rinfo->dir_nr, parent);
++              doutc(cl, "%d items under dn %p\n", rinfo->dir_nr, parent);
+               if (rinfo->dir_dir)
+                       ceph_fill_dirfrag(d_inode(parent), rinfo->dir_dir);
+@@ -1950,15 +1976,15 @@ int ceph_readdir_prepopulate(struct ceph
+ retry_lookup:
+               dn = d_lookup(parent, &dname);
+-              dout("d_lookup on parent=%p name=%.*s got %p\n",
+-                   parent, dname.len, dname.name, dn);
++              doutc(cl, "d_lookup on parent=%p name=%.*s got %p\n",
++                    parent, dname.len, dname.name, dn);
+               if (!dn) {
+                       dn = d_alloc(parent, &dname);
+-                      dout("d_alloc %p '%.*s' = %p\n", parent,
+-                           dname.len, dname.name, dn);
++                      doutc(cl, "d_alloc %p '%.*s' = %p\n", parent,
++                            dname.len, dname.name, dn);
+                       if (!dn) {
+-                              dout("d_alloc badness\n");
++                              doutc(cl, "d_alloc badness\n");
+                               err = -ENOMEM;
+                               goto out;
+                       }
+@@ -1971,8 +1997,8 @@ retry_lookup:
+                          (ceph_ino(d_inode(dn)) != tvino.ino ||
+                           ceph_snap(d_inode(dn)) != tvino.snap)) {
+                       struct ceph_dentry_info *di = ceph_dentry(dn);
+-                      dout(" dn %p points to wrong inode %p\n",
+-                           dn, d_inode(dn));
++                      doutc(cl, " dn %p points to wrong inode %p\n",
++                            dn, d_inode(dn));
+                       spin_lock(&dn->d_lock);
+                       if (di->offset > 0 &&
+@@ -1994,7 +2020,7 @@ retry_lookup:
+               } else {
+                       in = ceph_get_inode(parent->d_sb, tvino, NULL);
+                       if (IS_ERR(in)) {
+-                              dout("new_inode badness\n");
++                              doutc(cl, "new_inode badness\n");
+                               d_drop(dn);
+                               dput(dn);
+                               err = PTR_ERR(in);
+@@ -2005,7 +2031,8 @@ retry_lookup:
+               ret = ceph_fill_inode(in, NULL, &rde->inode, NULL, session,
+                                     -1, &req->r_caps_reservation);
+               if (ret < 0) {
+-                      pr_err("ceph_fill_inode badness on %p\n", in);
++                      pr_err_client(cl, "badness on %p %llx.%llx\n", in,
++                                    ceph_vinop(in));
+                       if (d_really_is_negative(dn)) {
+                               if (in->i_state & I_NEW) {
+                                       ihold(in);
+@@ -2022,8 +2049,8 @@ retry_lookup:
+               if (d_really_is_negative(dn)) {
+                       if (ceph_security_xattr_deadlock(in)) {
+-                              dout(" skip splicing dn %p to inode %p"
+-                                   " (security xattr deadlock)\n", dn, in);
++                              doutc(cl, " skip splicing dn %p to inode %p"
++                                    " (security xattr deadlock)\n", dn, in);
+                               iput(in);
+                               skipped++;
+                               goto next_item;
+@@ -2055,17 +2082,18 @@ out:
+               req->r_readdir_cache_idx = cache_ctl.index;
+       }
+       ceph_readdir_cache_release(&cache_ctl);
+-      dout("readdir_prepopulate done\n");
++      doutc(cl, "done\n");
+       return err;
+ }
+ bool ceph_inode_set_size(struct inode *inode, loff_t size)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       bool ret;
+       spin_lock(&ci->i_ceph_lock);
+-      dout("set_size %p %llu -> %llu\n", inode, i_size_read(inode), size);
++      doutc(cl, "set_size %p %llu -> %llu\n", inode, i_size_read(inode), size);
+       i_size_write(inode, size);
+       ceph_fscache_update(inode);
+       inode->i_blocks = calc_inode_blocks(size);
+@@ -2080,21 +2108,24 @@ bool ceph_inode_set_size(struct inode *i
+ void ceph_queue_inode_work(struct inode *inode, int work_bit)
+ {
+       struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       set_bit(work_bit, &ci->i_work_mask);
+       ihold(inode);
+       if (queue_work(fsc->inode_wq, &ci->i_work)) {
+-              dout("queue_inode_work %p, mask=%lx\n", inode, ci->i_work_mask);
++              doutc(cl, "%p %llx.%llx mask=%lx\n", inode,
++                    ceph_vinop(inode), ci->i_work_mask);
+       } else {
+-              dout("queue_inode_work %p already queued, mask=%lx\n",
+-                   inode, ci->i_work_mask);
++              doutc(cl, "%p %llx.%llx already queued, mask=%lx\n",
++                    inode, ceph_vinop(inode), ci->i_work_mask);
+               iput(inode);
+       }
+ }
+ static void ceph_do_invalidate_pages(struct inode *inode)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       u32 orig_gen;
+       int check = 0;
+@@ -2104,8 +2135,9 @@ static void ceph_do_invalidate_pages(str
+       mutex_lock(&ci->i_truncate_mutex);
+       if (ceph_inode_is_shutdown(inode)) {
+-              pr_warn_ratelimited("%s: inode %llx.%llx is shut down\n",
+-                                  __func__, ceph_vinop(inode));
++              pr_warn_ratelimited_client(cl,
++                      "%p %llx.%llx is shut down\n", inode,
++                      ceph_vinop(inode));
+               mapping_set_error(inode->i_mapping, -EIO);
+               truncate_pagecache(inode, 0);
+               mutex_unlock(&ci->i_truncate_mutex);
+@@ -2113,8 +2145,8 @@ static void ceph_do_invalidate_pages(str
+       }
+       spin_lock(&ci->i_ceph_lock);
+-      dout("invalidate_pages %p gen %d revoking %d\n", inode,
+-           ci->i_rdcache_gen, ci->i_rdcache_revoking);
++      doutc(cl, "%p %llx.%llx gen %d revoking %d\n", inode,
++            ceph_vinop(inode), ci->i_rdcache_gen, ci->i_rdcache_revoking);
+       if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
+               if (__ceph_caps_revoking_other(ci, NULL, CEPH_CAP_FILE_CACHE))
+                       check = 1;
+@@ -2126,21 +2158,21 @@ static void ceph_do_invalidate_pages(str
+       spin_unlock(&ci->i_ceph_lock);
+       if (invalidate_inode_pages2(inode->i_mapping) < 0) {
+-              pr_err("invalidate_inode_pages2 %llx.%llx failed\n",
+-                     ceph_vinop(inode));
++              pr_err_client(cl, "invalidate_inode_pages2 %llx.%llx failed\n",
++                            ceph_vinop(inode));
+       }
+       spin_lock(&ci->i_ceph_lock);
+       if (orig_gen == ci->i_rdcache_gen &&
+           orig_gen == ci->i_rdcache_revoking) {
+-              dout("invalidate_pages %p gen %d successful\n", inode,
+-                   ci->i_rdcache_gen);
++              doutc(cl, "%p %llx.%llx gen %d successful\n", inode,
++                    ceph_vinop(inode), ci->i_rdcache_gen);
+               ci->i_rdcache_revoking--;
+               check = 1;
+       } else {
+-              dout("invalidate_pages %p gen %d raced, now %d revoking %d\n",
+-                   inode, orig_gen, ci->i_rdcache_gen,
+-                   ci->i_rdcache_revoking);
++              doutc(cl, "%p %llx.%llx gen %d raced, now %d revoking %d\n",
++                    inode, ceph_vinop(inode), orig_gen, ci->i_rdcache_gen,
++                    ci->i_rdcache_revoking);
+               if (__ceph_caps_revoking_other(ci, NULL, CEPH_CAP_FILE_CACHE))
+                       check = 1;
+       }
+@@ -2157,6 +2189,7 @@ out:
+  */
+ void __ceph_do_pending_vmtruncate(struct inode *inode)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       u64 to;
+       int wrbuffer_refs, finish = 0;
+@@ -2165,7 +2198,8 @@ void __ceph_do_pending_vmtruncate(struct
+ retry:
+       spin_lock(&ci->i_ceph_lock);
+       if (ci->i_truncate_pending == 0) {
+-              dout("%s %p none pending\n", __func__, inode);
++              doutc(cl, "%p %llx.%llx none pending\n", inode,
++                    ceph_vinop(inode));
+               spin_unlock(&ci->i_ceph_lock);
+               mutex_unlock(&ci->i_truncate_mutex);
+               return;
+@@ -2177,7 +2211,8 @@ retry:
+        */
+       if (ci->i_wrbuffer_ref_head < ci->i_wrbuffer_ref) {
+               spin_unlock(&ci->i_ceph_lock);
+-              dout("%s %p flushing snaps first\n", __func__, inode);
++              doutc(cl, "%p %llx.%llx flushing snaps first\n", inode,
++                    ceph_vinop(inode));
+               filemap_write_and_wait_range(&inode->i_data, 0,
+                                            inode->i_sb->s_maxbytes);
+               goto retry;
+@@ -2188,8 +2223,8 @@ retry:
+       to = ci->i_truncate_pagecache_size;
+       wrbuffer_refs = ci->i_wrbuffer_ref;
+-      dout("%s %p (%d) to %lld\n", __func__, inode,
+-           ci->i_truncate_pending, to);
++      doutc(cl, "%p %llx.%llx (%d) to %lld\n", inode, ceph_vinop(inode),
++            ci->i_truncate_pending, to);
+       spin_unlock(&ci->i_ceph_lock);
+       ceph_fscache_resize(inode, to);
+@@ -2217,9 +2252,10 @@ static void ceph_inode_work(struct work_
+       struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info,
+                                                i_work);
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       if (test_and_clear_bit(CEPH_I_WORK_WRITEBACK, &ci->i_work_mask)) {
+-              dout("writeback %p\n", inode);
++              doutc(cl, "writeback %p %llx.%llx\n", inode, ceph_vinop(inode));
+               filemap_fdatawrite(&inode->i_data);
+       }
+       if (test_and_clear_bit(CEPH_I_WORK_INVALIDATE_PAGES, &ci->i_work_mask))
+@@ -2291,6 +2327,7 @@ static int fill_fscrypt_truncate(struct
+                                struct ceph_mds_request *req,
+                                struct iattr *attr)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       int boff = attr->ia_size % CEPH_FSCRYPT_BLOCK_SIZE;
+       loff_t pos, orig_pos = round_down(attr->ia_size,
+@@ -2313,9 +2350,9 @@ static int fill_fscrypt_truncate(struct
+       issued = __ceph_caps_issued(ci, NULL);
+-      dout("%s size %lld -> %lld got cap refs on %s, issued %s\n", __func__,
+-           i_size, attr->ia_size, ceph_cap_string(got),
+-           ceph_cap_string(issued));
++      doutc(cl, "size %lld -> %lld got cap refs on %s, issued %s\n",
++            i_size, attr->ia_size, ceph_cap_string(got),
++            ceph_cap_string(issued));
+       /* Try to writeback the dirty pagecaches */
+       if (issued & (CEPH_CAP_FILE_BUFFER)) {
+@@ -2370,8 +2407,7 @@ static int fill_fscrypt_truncate(struct
+        * If the Rados object doesn't exist, it will be set to 0.
+        */
+       if (!objver) {
+-              dout("%s hit hole, ppos %lld < size %lld\n", __func__,
+-                   pos, i_size);
++              doutc(cl, "hit hole, ppos %lld < size %lld\n", pos, i_size);
+               header.data_len = cpu_to_le32(8 + 8 + 4);
+               header.file_offset = 0;
+@@ -2380,8 +2416,8 @@ static int fill_fscrypt_truncate(struct
+               header.data_len = cpu_to_le32(8 + 8 + 4 + CEPH_FSCRYPT_BLOCK_SIZE);
+               header.file_offset = cpu_to_le64(orig_pos);
+-              dout("%s encrypt block boff/bsize %d/%lu\n", __func__,
+-                   boff, CEPH_FSCRYPT_BLOCK_SIZE);
++              doutc(cl, "encrypt block boff/bsize %d/%lu\n", boff,
++                    CEPH_FSCRYPT_BLOCK_SIZE);
+               /* truncate and zero out the extra contents for the last block */
+               memset(iov.iov_base + boff, 0, PAGE_SIZE - boff);
+@@ -2409,8 +2445,8 @@ static int fill_fscrypt_truncate(struct
+       }
+       req->r_pagelist = pagelist;
+ out:
+-      dout("%s %p size dropping cap refs on %s\n", __func__,
+-           inode, ceph_cap_string(got));
++      doutc(cl, "%p %llx.%llx size dropping cap refs on %s\n", inode,
++            ceph_vinop(inode), ceph_cap_string(got));
+       ceph_put_cap_refs(ci, got);
+       if (iov.iov_base)
+               kunmap_local(iov.iov_base);
+@@ -2428,6 +2464,7 @@ int __ceph_setattr(struct inode *inode,
+       unsigned int ia_valid = attr->ia_valid;
+       struct ceph_mds_request *req;
+       struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_cap_flush *prealloc_cf;
+       loff_t isize = i_size_read(inode);
+       int issued;
+@@ -2466,7 +2503,8 @@ retry:
+               }
+       }
+-      dout("setattr %p issued %s\n", inode, ceph_cap_string(issued));
++      doutc(cl, "%p %llx.%llx issued %s\n", inode, ceph_vinop(inode),
++            ceph_cap_string(issued));
+ #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
+       if (cia && cia->fscrypt_auth) {
+               u32 len = ceph_fscrypt_auth_len(cia->fscrypt_auth);
+@@ -2477,8 +2515,8 @@ retry:
+                       goto out;
+               }
+-              dout("setattr %llx:%llx fscrypt_auth len %u to %u)\n",
+-                      ceph_vinop(inode), ci->fscrypt_auth_len, len);
++              doutc(cl, "%p %llx.%llx fscrypt_auth len %u to %u)\n", inode,
++                    ceph_vinop(inode), ci->fscrypt_auth_len, len);
+               /* It should never be re-set once set */
+               WARN_ON_ONCE(ci->fscrypt_auth);
+@@ -2506,9 +2544,10 @@ retry:
+ #endif /* CONFIG_FS_ENCRYPTION */
+       if (ia_valid & ATTR_UID) {
+-              dout("setattr %p uid %d -> %d\n", inode,
+-                   from_kuid(&init_user_ns, inode->i_uid),
+-                   from_kuid(&init_user_ns, attr->ia_uid));
++              doutc(cl, "%p %llx.%llx uid %d -> %d\n", inode,
++                    ceph_vinop(inode),
++                    from_kuid(&init_user_ns, inode->i_uid),
++                    from_kuid(&init_user_ns, attr->ia_uid));
+               if (issued & CEPH_CAP_AUTH_EXCL) {
+                       inode->i_uid = attr->ia_uid;
+                       dirtied |= CEPH_CAP_AUTH_EXCL;
+@@ -2521,9 +2560,10 @@ retry:
+               }
+       }
+       if (ia_valid & ATTR_GID) {
+-              dout("setattr %p gid %d -> %d\n", inode,
+-                   from_kgid(&init_user_ns, inode->i_gid),
+-                   from_kgid(&init_user_ns, attr->ia_gid));
++              doutc(cl, "%p %llx.%llx gid %d -> %d\n", inode,
++                    ceph_vinop(inode),
++                    from_kgid(&init_user_ns, inode->i_gid),
++                    from_kgid(&init_user_ns, attr->ia_gid));
+               if (issued & CEPH_CAP_AUTH_EXCL) {
+                       inode->i_gid = attr->ia_gid;
+                       dirtied |= CEPH_CAP_AUTH_EXCL;
+@@ -2536,8 +2576,8 @@ retry:
+               }
+       }
+       if (ia_valid & ATTR_MODE) {
+-              dout("setattr %p mode 0%o -> 0%o\n", inode, inode->i_mode,
+-                   attr->ia_mode);
++              doutc(cl, "%p %llx.%llx mode 0%o -> 0%o\n", inode,
++                    ceph_vinop(inode), inode->i_mode, attr->ia_mode);
+               if (issued & CEPH_CAP_AUTH_EXCL) {
+                       inode->i_mode = attr->ia_mode;
+                       dirtied |= CEPH_CAP_AUTH_EXCL;
+@@ -2551,9 +2591,10 @@ retry:
+       }
+       if (ia_valid & ATTR_ATIME) {
+-              dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode,
+-                   inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
+-                   attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
++              doutc(cl, "%p %llx.%llx atime %lld.%ld -> %lld.%ld\n",
++                    inode, ceph_vinop(inode), inode->i_atime.tv_sec,
++                    inode->i_atime.tv_nsec, attr->ia_atime.tv_sec,
++                    attr->ia_atime.tv_nsec);
+               if (issued & CEPH_CAP_FILE_EXCL) {
+                       ci->i_time_warp_seq++;
+                       inode->i_atime = attr->ia_atime;
+@@ -2573,7 +2614,8 @@ retry:
+               }
+       }
+       if (ia_valid & ATTR_SIZE) {
+-              dout("setattr %p size %lld -> %lld\n", inode, isize, attr->ia_size);
++              doutc(cl, "%p %llx.%llx size %lld -> %lld\n", inode,
++                    ceph_vinop(inode), isize, attr->ia_size);
+               /*
+                * Only when the new size is smaller and not aligned to
+                * CEPH_FSCRYPT_BLOCK_SIZE will the RMW is needed.
+@@ -2624,9 +2666,10 @@ retry:
+               }
+       }
+       if (ia_valid & ATTR_MTIME) {
+-              dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode,
+-                   inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+-                   attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
++              doutc(cl, "%p %llx.%llx mtime %lld.%ld -> %lld.%ld\n",
++                    inode, ceph_vinop(inode), inode->i_mtime.tv_sec,
++                    inode->i_mtime.tv_nsec, attr->ia_mtime.tv_sec,
++                    attr->ia_mtime.tv_nsec);
+               if (issued & CEPH_CAP_FILE_EXCL) {
+                       ci->i_time_warp_seq++;
+                       inode->i_mtime = attr->ia_mtime;
+@@ -2650,11 +2693,12 @@ retry:
+       if (ia_valid & ATTR_CTIME) {
+               bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME|
+                                        ATTR_MODE|ATTR_UID|ATTR_GID)) == 0;
+-              dout("setattr %p ctime %lld.%ld -> %lld.%ld (%s)\n", inode,
+-                   inode_get_ctime(inode).tv_sec,
+-                   inode_get_ctime(inode).tv_nsec,
+-                   attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
+-                   only ? "ctime only" : "ignored");
++              doutc(cl, "%p %llx.%llx ctime %lld.%ld -> %lld.%ld (%s)\n",
++                    inode, ceph_vinop(inode), inode_get_ctime(inode).tv_sec,
++                    inode_get_ctime(inode).tv_nsec,
++                    attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
++                    only ? "ctime only" : "ignored");
++
+               if (only) {
+                       /*
+                        * if kernel wants to dirty ctime but nothing else,
+@@ -2672,7 +2716,8 @@ retry:
+               }
+       }
+       if (ia_valid & ATTR_FILE)
+-              dout("setattr %p ATTR_FILE ... hrm!\n", inode);
++              doutc(cl, "%p %llx.%llx ATTR_FILE ... hrm!\n", inode,
++                    ceph_vinop(inode));
+       if (dirtied) {
+               inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied,
+@@ -2713,16 +2758,17 @@ retry:
+                */
+               err = ceph_mdsc_do_request(mdsc, NULL, req);
+               if (err == -EAGAIN && truncate_retry--) {
+-                      dout("setattr %p result=%d (%s locally, %d remote), retry it!\n",
+-                           inode, err, ceph_cap_string(dirtied), mask);
++                      doutc(cl, "%p %llx.%llx result=%d (%s locally, %d remote), retry it!\n",
++                            inode, ceph_vinop(inode), err,
++                            ceph_cap_string(dirtied), mask);
+                       ceph_mdsc_put_request(req);
+                       ceph_free_cap_flush(prealloc_cf);
+                       goto retry;
+               }
+       }
+ out:
+-      dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
+-           ceph_cap_string(dirtied), mask);
++      doutc(cl, "%p %llx.%llx result=%d (%s locally, %d remote)\n", inode,
++            ceph_vinop(inode), err, ceph_cap_string(dirtied), mask);
+       ceph_mdsc_put_request(req);
+       ceph_free_cap_flush(prealloc_cf);
+@@ -2811,18 +2857,20 @@ int __ceph_do_getattr(struct inode *inod
+                     int mask, bool force)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       struct ceph_mds_request *req;
+       int mode;
+       int err;
+       if (ceph_snap(inode) == CEPH_SNAPDIR) {
+-              dout("do_getattr inode %p SNAPDIR\n", inode);
++              doutc(cl, "inode %p %llx.%llx SNAPDIR\n", inode,
++                    ceph_vinop(inode));
+               return 0;
+       }
+-      dout("do_getattr inode %p mask %s mode 0%o\n",
+-           inode, ceph_cap_string(mask), inode->i_mode);
++      doutc(cl, "inode %p %llx.%llx mask %s mode 0%o\n", inode,
++            ceph_vinop(inode), ceph_cap_string(mask), inode->i_mode);
+       if (!force && ceph_caps_issued_mask_metric(ceph_inode(inode), mask, 1))
+                       return 0;
+@@ -2849,7 +2897,7 @@ int __ceph_do_getattr(struct inode *inod
+               }
+       }
+       ceph_mdsc_put_request(req);
+-      dout("do_getattr result=%d\n", err);
++      doutc(cl, "result=%d\n", err);
+       return err;
+ }
+@@ -2857,6 +2905,7 @@ int ceph_do_getvxattr(struct inode *inod
+                     size_t size)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       struct ceph_mds_request *req;
+       int mode = USE_AUTH_MDS;
+@@ -2886,7 +2935,7 @@ int ceph_do_getvxattr(struct inode *inod
+       xattr_value = req->r_reply_info.xattr_info.xattr_value;
+       xattr_value_len = req->r_reply_info.xattr_info.xattr_value_len;
+-      dout("do_getvxattr xattr_value_len:%zu, size:%zu\n", xattr_value_len, size);
++      doutc(cl, "xattr_value_len:%zu, size:%zu\n", xattr_value_len, size);
+       err = (int)xattr_value_len;
+       if (size == 0)
+@@ -2901,7 +2950,7 @@ int ceph_do_getvxattr(struct inode *inod
+ put:
+       ceph_mdsc_put_request(req);
+ out:
+-      dout("do_getvxattr result=%d\n", err);
++      doutc(cl, "result=%d\n", err);
+       return err;
+ }
+--- a/fs/ceph/ioctl.c
++++ b/fs/ceph/ioctl.c
+@@ -245,6 +245,7 @@ static long ceph_ioctl_lazyio(struct fil
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) {
+               spin_lock(&ci->i_ceph_lock);
+@@ -252,11 +253,13 @@ static long ceph_ioctl_lazyio(struct fil
+               ci->i_nr_by_mode[ffs(CEPH_FILE_MODE_LAZY)]++;
+               __ceph_touch_fmode(ci, mdsc, fi->fmode);
+               spin_unlock(&ci->i_ceph_lock);
+-              dout("ioctl_layzio: file %p marked lazy\n", file);
++              doutc(cl, "file %p %p %llx.%llx marked lazy\n", file, inode,
++                    ceph_vinop(inode));
+               ceph_check_caps(ci, 0);
+       } else {
+-              dout("ioctl_layzio: file %p already lazy\n", file);
++              doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode,
++                    ceph_vinop(inode));
+       }
+       return 0;
+ }
+@@ -355,10 +358,12 @@ static const char *ceph_ioctl_cmd_name(c
+ long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
++      struct inode *inode = file_inode(file);
++      struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+       int ret;
+-      dout("ioctl file %p cmd %s arg %lu\n", file,
+-           ceph_ioctl_cmd_name(cmd), arg);
++      doutc(fsc->client, "file %p %p %llx.%llx cmd %s arg %lu\n", file,
++            inode, ceph_vinop(inode), ceph_ioctl_cmd_name(cmd), arg);
+       switch (cmd) {
+       case CEPH_IOC_GET_LAYOUT:
+               return ceph_ioctl_get_layout(file, (void __user *)arg);
+--- a/fs/ceph/locks.c
++++ b/fs/ceph/locks.c
+@@ -77,6 +77,7 @@ static int ceph_lock_message(u8 lock_typ
+                            int cmd, u8 wait, struct file_lock *fl)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       int err;
+       u64 length = 0;
+@@ -111,10 +112,10 @@ static int ceph_lock_message(u8 lock_typ
+       owner = secure_addr(fl->fl_owner);
+-      dout("ceph_lock_message: rule: %d, op: %d, owner: %llx, pid: %llu, "
+-           "start: %llu, length: %llu, wait: %d, type: %d\n", (int)lock_type,
+-           (int)operation, owner, (u64)fl->fl_pid, fl->fl_start, length,
+-           wait, fl->fl_type);
++      doutc(cl, "rule: %d, op: %d, owner: %llx, pid: %llu, "
++                  "start: %llu, length: %llu, wait: %d, type: %d\n",
++                  (int)lock_type, (int)operation, owner, (u64)fl->fl_pid,
++                  fl->fl_start, length, wait, fl->fl_type);
+       req->r_args.filelock_change.rule = lock_type;
+       req->r_args.filelock_change.type = cmd;
+@@ -147,16 +148,17 @@ static int ceph_lock_message(u8 lock_typ
+       }
+       ceph_mdsc_put_request(req);
+-      dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
+-           "length: %llu, wait: %d, type: %d, err code %d\n", (int)lock_type,
+-           (int)operation, (u64)fl->fl_pid, fl->fl_start,
+-           length, wait, fl->fl_type, err);
++      doutc(cl, "rule: %d, op: %d, pid: %llu, start: %llu, "
++            "length: %llu, wait: %d, type: %d, err code %d\n",
++            (int)lock_type, (int)operation, (u64)fl->fl_pid,
++            fl->fl_start, length, wait, fl->fl_type, err);
+       return err;
+ }
+ static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
+                                          struct ceph_mds_request *req)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *intr_req;
+       struct inode *inode = req->r_inode;
+       int err, lock_type;
+@@ -174,8 +176,7 @@ static int ceph_lock_wait_for_completion
+       if (!err)
+               return 0;
+-      dout("ceph_lock_wait_for_completion: request %llu was interrupted\n",
+-           req->r_tid);
++      doutc(cl, "request %llu was interrupted\n", req->r_tid);
+       mutex_lock(&mdsc->mutex);
+       if (test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
+@@ -249,6 +250,7 @@ int ceph_lock(struct file *file, int cmd
+ {
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int err = 0;
+       u16 op = CEPH_MDS_OP_SETFILELOCK;
+       u8 wait = 0;
+@@ -260,7 +262,7 @@ int ceph_lock(struct file *file, int cmd
+       if (ceph_inode_is_shutdown(inode))
+               return -ESTALE;
+-      dout("ceph_lock, fl_owner: %p\n", fl->fl_owner);
++      doutc(cl, "fl_owner: %p\n", fl->fl_owner);
+       /* set wait bit as appropriate, then make command as Ceph expects it*/
+       if (IS_GETLK(cmd))
+@@ -295,7 +297,7 @@ int ceph_lock(struct file *file, int cmd
+       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, inode, lock_cmd, wait, fl);
+       if (!err) {
+               if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK != fl->fl_type) {
+-                      dout("mds locked, locking locally\n");
++                      doutc(cl, "locking locally\n");
+                       err = posix_lock_file(file, fl, NULL);
+                       if (err) {
+                               /* undo! This should only happen if
+@@ -303,8 +305,8 @@ int ceph_lock(struct file *file, int cmd
+                                * deadlock. */
+                               ceph_lock_message(CEPH_LOCK_FCNTL, op, inode,
+                                                 CEPH_LOCK_UNLOCK, 0, fl);
+-                              dout("got %d on posix_lock_file, undid lock\n",
+-                                   err);
++                              doutc(cl, "got %d on posix_lock_file, undid lock\n",
++                                    err);
+                       }
+               }
+       }
+@@ -315,6 +317,7 @@ int ceph_flock(struct file *file, int cm
+ {
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int err = 0;
+       u8 wait = 0;
+       u8 lock_cmd;
+@@ -325,7 +328,7 @@ int ceph_flock(struct file *file, int cm
+       if (ceph_inode_is_shutdown(inode))
+               return -ESTALE;
+-      dout("ceph_flock, fl_file: %p\n", fl->fl_file);
++      doutc(cl, "fl_file: %p\n", fl->fl_file);
+       spin_lock(&ci->i_ceph_lock);
+       if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) {
+@@ -362,7 +365,8 @@ int ceph_flock(struct file *file, int cm
+                       ceph_lock_message(CEPH_LOCK_FLOCK,
+                                         CEPH_MDS_OP_SETFILELOCK,
+                                         inode, CEPH_LOCK_UNLOCK, 0, fl);
+-                      dout("got %d on locks_lock_file_wait, undid lock\n", err);
++                      doutc(cl, "got %d on locks_lock_file_wait, undid lock\n",
++                            err);
+               }
+       }
+       return err;
+@@ -374,6 +378,7 @@ int ceph_flock(struct file *file, int cm
+  */
+ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct file_lock *lock;
+       struct file_lock_context *ctx;
+@@ -389,17 +394,20 @@ void ceph_count_locks(struct inode *inod
+                       ++(*flock_count);
+               spin_unlock(&ctx->flc_lock);
+       }
+-      dout("counted %d flock locks and %d fcntl locks\n",
+-           *flock_count, *fcntl_count);
++      doutc(cl, "counted %d flock locks and %d fcntl locks\n",
++            *flock_count, *fcntl_count);
+ }
+ /*
+  * Given a pointer to a lock, convert it to a ceph filelock
+  */
+-static int lock_to_ceph_filelock(struct file_lock *lock,
++static int lock_to_ceph_filelock(struct inode *inode,
++                               struct file_lock *lock,
+                                struct ceph_filelock *cephlock)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int err = 0;
++
+       cephlock->start = cpu_to_le64(lock->fl_start);
+       cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1);
+       cephlock->client = cpu_to_le64(0);
+@@ -417,7 +425,7 @@ static int lock_to_ceph_filelock(struct
+               cephlock->type = CEPH_LOCK_UNLOCK;
+               break;
+       default:
+-              dout("Have unknown lock type %d\n", lock->fl_type);
++              doutc(cl, "Have unknown lock type %d\n", lock->fl_type);
+               err = -EINVAL;
+       }
+@@ -435,13 +443,14 @@ int ceph_encode_locks_to_buffer(struct i
+ {
+       struct file_lock *lock;
+       struct file_lock_context *ctx = locks_inode_context(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       int err = 0;
+       int seen_fcntl = 0;
+       int seen_flock = 0;
+       int l = 0;
+-      dout("encoding %d flock and %d fcntl locks\n", num_flock_locks,
+-           num_fcntl_locks);
++      doutc(cl, "encoding %d flock and %d fcntl locks\n", num_flock_locks,
++            num_fcntl_locks);
+       if (!ctx)
+               return 0;
+@@ -453,7 +462,7 @@ int ceph_encode_locks_to_buffer(struct i
+                       err = -ENOSPC;
+                       goto fail;
+               }
+-              err = lock_to_ceph_filelock(lock, &flocks[l]);
++              err = lock_to_ceph_filelock(inode, lock, &flocks[l]);
+               if (err)
+                       goto fail;
+               ++l;
+@@ -464,7 +473,7 @@ int ceph_encode_locks_to_buffer(struct i
+                       err = -ENOSPC;
+                       goto fail;
+               }
+-              err = lock_to_ceph_filelock(lock, &flocks[l]);
++              err = lock_to_ceph_filelock(inode, lock, &flocks[l]);
+               if (err)
+                       goto fail;
+               ++l;
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -411,6 +411,7 @@ static int parse_reply_info_readdir(void
+                                   u64 features)
+ {
+       struct ceph_mds_reply_info_parsed *info = &req->r_reply_info;
++      struct ceph_client *cl = req->r_mdsc->fsc->client;
+       u32 num, i = 0;
+       int err;
+@@ -433,7 +434,7 @@ static int parse_reply_info_readdir(void
+       BUG_ON(!info->dir_entries);
+       if ((unsigned long)(info->dir_entries + num) >
+           (unsigned long)info->dir_entries + info->dir_buf_size) {
+-              pr_err("dir contents are larger than expected\n");
++              pr_err_client(cl, "dir contents are larger than expected\n");
+               WARN_ON(1);
+               goto bad;
+       }
+@@ -454,7 +455,7 @@ static int parse_reply_info_readdir(void
+               ceph_decode_need(p, end, _name_len, bad);
+               _name = *p;
+               *p += _name_len;
+-              dout("parsed dir dname '%.*s'\n", _name_len, _name);
++              doutc(cl, "parsed dir dname '%.*s'\n", _name_len, _name);
+               if (info->hash_order)
+                       rde->raw_hash = ceph_str_hash(ci->i_dir_layout.dl_dir_hash,
+@@ -514,8 +515,8 @@ static int parse_reply_info_readdir(void
+               rde->is_nokey = false;
+               err = ceph_fname_to_usr(&fname, &tname, &oname, &rde->is_nokey);
+               if (err) {
+-                      pr_err("%s unable to decode %.*s, got %d\n", __func__,
+-                             _name_len, _name, err);
++                      pr_err_client(cl, "unable to decode %.*s, got %d\n",
++                                    _name_len, _name, err);
+                       goto out_bad;
+               }
+               rde->name = oname.name;
+@@ -539,7 +540,7 @@ done:
+ bad:
+       err = -EIO;
+ out_bad:
+-      pr_err("problem parsing dir contents %d\n", err);
++      pr_err_client(cl, "problem parsing dir contents %d\n", err);
+       return err;
+ }
+@@ -570,10 +571,11 @@ bad:
+ static int ceph_parse_deleg_inos(void **p, void *end,
+                                struct ceph_mds_session *s)
+ {
++      struct ceph_client *cl = s->s_mdsc->fsc->client;
+       u32 sets;
+       ceph_decode_32_safe(p, end, sets, bad);
+-      dout("got %u sets of delegated inodes\n", sets);
++      doutc(cl, "got %u sets of delegated inodes\n", sets);
+       while (sets--) {
+               u64 start, len;
+@@ -582,8 +584,9 @@ static int ceph_parse_deleg_inos(void **
+               /* Don't accept a delegation of system inodes */
+               if (start < CEPH_INO_SYSTEM_BASE) {
+-                      pr_warn_ratelimited("ceph: ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n",
+-                                      start, len);
++                      pr_warn_ratelimited_client(cl,
++                              "ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n",
++                              start, len);
+                       continue;
+               }
+               while (len--) {
+@@ -591,10 +594,10 @@ static int ceph_parse_deleg_inos(void **
+                                           DELEGATED_INO_AVAILABLE,
+                                           GFP_KERNEL);
+                       if (!err) {
+-                              dout("added delegated inode 0x%llx\n",
+-                                   start - 1);
++                              doutc(cl, "added delegated inode 0x%llx\n", start - 1);
+                       } else if (err == -EBUSY) {
+-                              pr_warn("MDS delegated inode 0x%llx more than once.\n",
++                              pr_warn_client(cl,
++                                      "MDS delegated inode 0x%llx more than once.\n",
+                                       start - 1);
+                       } else {
+                               return err;
+@@ -744,6 +747,7 @@ static int parse_reply_info(struct ceph_
+                           struct ceph_mds_request *req, u64 features)
+ {
+       struct ceph_mds_reply_info_parsed *info = &req->r_reply_info;
++      struct ceph_client *cl = s->s_mdsc->fsc->client;
+       void *p, *end;
+       u32 len;
+       int err;
+@@ -783,7 +787,7 @@ static int parse_reply_info(struct ceph_
+ bad:
+       err = -EIO;
+ out_bad:
+-      pr_err("mds parse_reply err %d\n", err);
++      pr_err_client(cl, "mds parse_reply err %d\n", err);
+       ceph_msg_dump(msg);
+       return err;
+ }
+@@ -831,6 +835,7 @@ static void destroy_reply_info(struct ce
+ int ceph_wait_on_conflict_unlink(struct dentry *dentry)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
++      struct ceph_client *cl = fsc->client;
+       struct dentry *pdentry = dentry->d_parent;
+       struct dentry *udentry, *found = NULL;
+       struct ceph_dentry_info *di;
+@@ -855,8 +860,8 @@ int ceph_wait_on_conflict_unlink(struct
+                       goto next;
+               if (!test_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags))
+-                      pr_warn("%s dentry %p:%pd async unlink bit is not set\n",
+-                              __func__, dentry, dentry);
++                      pr_warn_client(cl, "dentry %p:%pd async unlink bit is not set\n",
++                                     dentry, dentry);
+               if (!d_same_name(udentry, pdentry, &dname))
+                       goto next;
+@@ -872,8 +877,8 @@ next:
+       if (likely(!found))
+               return 0;
+-      dout("%s dentry %p:%pd conflict with old %p:%pd\n", __func__,
+-           dentry, dentry, found, found);
++      doutc(cl, "dentry %p:%pd conflict with old %p:%pd\n", dentry, dentry,
++            found, found);
+       err = wait_on_bit(&di->flags, CEPH_DENTRY_ASYNC_UNLINK_BIT,
+                         TASK_KILLABLE);
+@@ -957,6 +962,7 @@ static int __verify_registered_session(s
+ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
+                                                int mds)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_session *s;
+       if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO)
+@@ -973,7 +979,7 @@ static struct ceph_mds_session *register
+               int newmax = 1 << get_count_order(mds + 1);
+               struct ceph_mds_session **sa;
+-              dout("%s: realloc to %d\n", __func__, newmax);
++              doutc(cl, "realloc to %d\n", newmax);
+               sa = kcalloc(newmax, sizeof(void *), GFP_NOFS);
+               if (!sa)
+                       goto fail_realloc;
+@@ -986,7 +992,7 @@ static struct ceph_mds_session *register
+               mdsc->max_sessions = newmax;
+       }
+-      dout("%s: mds%d\n", __func__, mds);
++      doutc(cl, "mds%d\n", mds);
+       s->s_mdsc = mdsc;
+       s->s_mds = mds;
+       s->s_state = CEPH_MDS_SESSION_NEW;
+@@ -1029,7 +1035,7 @@ fail_realloc:
+ static void __unregister_session(struct ceph_mds_client *mdsc,
+                              struct ceph_mds_session *s)
+ {
+-      dout("__unregister_session mds%d %p\n", s->s_mds, s);
++      doutc(mdsc->fsc->client, "mds%d %p\n", s->s_mds, s);
+       BUG_ON(mdsc->sessions[s->s_mds] != s);
+       mdsc->sessions[s->s_mds] = NULL;
+       ceph_con_close(&s->s_con);
+@@ -1155,6 +1161,7 @@ static void __register_request(struct ce
+                              struct ceph_mds_request *req,
+                              struct inode *dir)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int ret = 0;
+       req->r_tid = ++mdsc->last_tid;
+@@ -1162,14 +1169,14 @@ static void __register_request(struct ce
+               ret = ceph_reserve_caps(mdsc, &req->r_caps_reservation,
+                                       req->r_num_caps);
+               if (ret < 0) {
+-                      pr_err("__register_request %p "
+-                             "failed to reserve caps: %d\n", req, ret);
++                      pr_err_client(cl, "%p failed to reserve caps: %d\n",
++                                    req, ret);
+                       /* set req->r_err to fail early from __do_request */
+                       req->r_err = ret;
+                       return;
+               }
+       }
+-      dout("__register_request %p tid %lld\n", req, req->r_tid);
++      doutc(cl, "%p tid %lld\n", req, req->r_tid);
+       ceph_mdsc_get_request(req);
+       insert_request(&mdsc->request_tree, req);
+@@ -1192,7 +1199,7 @@ static void __register_request(struct ce
+ static void __unregister_request(struct ceph_mds_client *mdsc,
+                                struct ceph_mds_request *req)
+ {
+-      dout("__unregister_request %p tid %lld\n", req, req->r_tid);
++      doutc(mdsc->fsc->client, "%p tid %lld\n", req, req->r_tid);
+       /* Never leave an unregistered request on an unsafe list! */
+       list_del_init(&req->r_unsafe_item);
+@@ -1278,6 +1285,7 @@ static int __choose_mds(struct ceph_mds_
+       int mds = -1;
+       u32 hash = req->r_direct_hash;
+       bool is_hash = test_bit(CEPH_MDS_R_DIRECT_IS_HASH, &req->r_req_flags);
++      struct ceph_client *cl = mdsc->fsc->client;
+       if (random)
+               *random = false;
+@@ -1289,8 +1297,7 @@ static int __choose_mds(struct ceph_mds_
+       if (req->r_resend_mds >= 0 &&
+           (__have_session(mdsc, req->r_resend_mds) ||
+            ceph_mdsmap_get_state(mdsc->mdsmap, req->r_resend_mds) > 0)) {
+-              dout("%s using resend_mds mds%d\n", __func__,
+-                   req->r_resend_mds);
++              doutc(cl, "using resend_mds mds%d\n", req->r_resend_mds);
+               return req->r_resend_mds;
+       }
+@@ -1307,7 +1314,8 @@ static int __choose_mds(struct ceph_mds_
+                       rcu_read_lock();
+                       inode = get_nonsnap_parent(req->r_dentry);
+                       rcu_read_unlock();
+-                      dout("%s using snapdir's parent %p\n", __func__, inode);
++                      doutc(cl, "using snapdir's parent %p %llx.%llx\n",
++                            inode, ceph_vinop(inode));
+               }
+       } else if (req->r_dentry) {
+               /* ignore race with rename; old or new d_parent is okay */
+@@ -1327,7 +1335,8 @@ static int __choose_mds(struct ceph_mds_
+                       /* direct snapped/virtual snapdir requests
+                        * based on parent dir inode */
+                       inode = get_nonsnap_parent(parent);
+-                      dout("%s using nonsnap parent %p\n", __func__, inode);
++                      doutc(cl, "using nonsnap parent %p %llx.%llx\n",
++                            inode, ceph_vinop(inode));
+               } else {
+                       /* dentry target */
+                       inode = d_inode(req->r_dentry);
+@@ -1343,10 +1352,11 @@ static int __choose_mds(struct ceph_mds_
+               rcu_read_unlock();
+       }
+-      dout("%s %p is_hash=%d (0x%x) mode %d\n", __func__, inode, (int)is_hash,
+-           hash, mode);
+       if (!inode)
+               goto random;
++
++      doutc(cl, "%p %llx.%llx is_hash=%d (0x%x) mode %d\n", inode,
++            ceph_vinop(inode), (int)is_hash, hash, mode);
+       ci = ceph_inode(inode);
+       if (is_hash && S_ISDIR(inode->i_mode)) {
+@@ -1362,9 +1372,9 @@ static int __choose_mds(struct ceph_mds_
+                               get_random_bytes(&r, 1);
+                               r %= frag.ndist;
+                               mds = frag.dist[r];
+-                              dout("%s %p %llx.%llx frag %u mds%d (%d/%d)\n",
+-                                   __func__, inode, ceph_vinop(inode),
+-                                   frag.frag, mds, (int)r, frag.ndist);
++                              doutc(cl, "%p %llx.%llx frag %u mds%d (%d/%d)\n",
++                                    inode, ceph_vinop(inode), frag.frag,
++                                    mds, (int)r, frag.ndist);
+                               if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >=
+                                   CEPH_MDS_STATE_ACTIVE &&
+                                   !ceph_mdsmap_is_laggy(mdsc->mdsmap, mds))
+@@ -1377,9 +1387,8 @@ static int __choose_mds(struct ceph_mds_
+                       if (frag.mds >= 0) {
+                               /* choose auth mds */
+                               mds = frag.mds;
+-                              dout("%s %p %llx.%llx frag %u mds%d (auth)\n",
+-                                   __func__, inode, ceph_vinop(inode),
+-                                   frag.frag, mds);
++                              doutc(cl, "%p %llx.%llx frag %u mds%d (auth)\n",
++                                    inode, ceph_vinop(inode), frag.frag, mds);
+                               if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >=
+                                   CEPH_MDS_STATE_ACTIVE) {
+                                       if (!ceph_mdsmap_is_laggy(mdsc->mdsmap,
+@@ -1403,9 +1412,9 @@ static int __choose_mds(struct ceph_mds_
+               goto random;
+       }
+       mds = cap->session->s_mds;
+-      dout("%s %p %llx.%llx mds%d (%scap %p)\n", __func__,
+-           inode, ceph_vinop(inode), mds,
+-           cap == ci->i_auth_cap ? "auth " : "", cap);
++      doutc(cl, "%p %llx.%llx mds%d (%scap %p)\n", inode,
++            ceph_vinop(inode), mds,
++            cap == ci->i_auth_cap ? "auth " : "", cap);
+       spin_unlock(&ci->i_ceph_lock);
+ out:
+       iput(inode);
+@@ -1416,7 +1425,7 @@ random:
+               *random = true;
+       mds = ceph_mdsmap_get_random_mds(mdsc->mdsmap);
+-      dout("%s chose random mds%d\n", __func__, mds);
++      doutc(cl, "chose random mds%d\n", mds);
+       return mds;
+ }
+@@ -1529,6 +1538,7 @@ static struct ceph_msg *create_session_o
+       int metadata_key_count = 0;
+       struct ceph_options *opt = mdsc->fsc->client->options;
+       struct ceph_mount_options *fsopt = mdsc->fsc->mount_options;
++      struct ceph_client *cl = mdsc->fsc->client;
+       size_t size, count;
+       void *p, *end;
+       int ret;
+@@ -1567,7 +1577,7 @@ static struct ceph_msg *create_session_o
+       msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + extra_bytes,
+                          GFP_NOFS, false);
+       if (!msg) {
+-              pr_err("ENOMEM creating session open msg\n");
++              pr_err_client(cl, "ENOMEM creating session open msg\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       p = msg->front.iov_base;
+@@ -1607,14 +1617,14 @@ static struct ceph_msg *create_session_o
+       ret = encode_supported_features(&p, end);
+       if (ret) {
+-              pr_err("encode_supported_features failed!\n");
++              pr_err_client(cl, "encode_supported_features failed!\n");
+               ceph_msg_put(msg);
+               return ERR_PTR(ret);
+       }
+       ret = encode_metric_spec(&p, end);
+       if (ret) {
+-              pr_err("encode_metric_spec failed!\n");
++              pr_err_client(cl, "encode_metric_spec failed!\n");
+               ceph_msg_put(msg);
+               return ERR_PTR(ret);
+       }
+@@ -1642,8 +1652,8 @@ static int __open_session(struct ceph_md
+       /* wait for mds to go active? */
+       mstate = ceph_mdsmap_get_state(mdsc->mdsmap, mds);
+-      dout("open_session to mds%d (%s)\n", mds,
+-           ceph_mds_state_name(mstate));
++      doutc(mdsc->fsc->client, "open_session to mds%d (%s)\n", mds,
++            ceph_mds_state_name(mstate));
+       session->s_state = CEPH_MDS_SESSION_OPENING;
+       session->s_renew_requested = jiffies;
+@@ -1686,8 +1696,9 @@ struct ceph_mds_session *
+ ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target)
+ {
+       struct ceph_mds_session *session;
++      struct ceph_client *cl = mdsc->fsc->client;
+-      dout("open_export_target_session to mds%d\n", target);
++      doutc(cl, "to mds%d\n", target);
+       mutex_lock(&mdsc->mutex);
+       session = __open_export_target_session(mdsc, target);
+@@ -1702,13 +1713,14 @@ static void __open_export_target_session
+       struct ceph_mds_info *mi;
+       struct ceph_mds_session *ts;
+       int i, mds = session->s_mds;
++      struct ceph_client *cl = mdsc->fsc->client;
+       if (mds >= mdsc->mdsmap->possible_max_rank)
+               return;
+       mi = &mdsc->mdsmap->m_info[mds];
+-      dout("open_export_target_sessions for mds%d (%d targets)\n",
+-           session->s_mds, mi->num_export_targets);
++      doutc(cl, "for mds%d (%d targets)\n", session->s_mds,
++            mi->num_export_targets);
+       for (i = 0; i < mi->num_export_targets; i++) {
+               ts = __open_export_target_session(mdsc, mi->export_targets[i]);
+@@ -1731,11 +1743,13 @@ void ceph_mdsc_open_export_target_sessio
+ static void detach_cap_releases(struct ceph_mds_session *session,
+                               struct list_head *target)
+ {
++      struct ceph_client *cl = session->s_mdsc->fsc->client;
++
+       lockdep_assert_held(&session->s_cap_lock);
+       list_splice_init(&session->s_cap_releases, target);
+       session->s_num_cap_releases = 0;
+-      dout("dispose_cap_releases mds%d\n", session->s_mds);
++      doutc(cl, "mds%d\n", session->s_mds);
+ }
+ static void dispose_cap_releases(struct ceph_mds_client *mdsc,
+@@ -1753,16 +1767,17 @@ static void dispose_cap_releases(struct
+ static void cleanup_session_requests(struct ceph_mds_client *mdsc,
+                                    struct ceph_mds_session *session)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       struct rb_node *p;
+-      dout("cleanup_session_requests mds%d\n", session->s_mds);
++      doutc(cl, "mds%d\n", session->s_mds);
+       mutex_lock(&mdsc->mutex);
+       while (!list_empty(&session->s_unsafe)) {
+               req = list_first_entry(&session->s_unsafe,
+                                      struct ceph_mds_request, r_unsafe_item);
+-              pr_warn_ratelimited(" dropping unsafe request %llu\n",
+-                                  req->r_tid);
++              pr_warn_ratelimited_client(cl, " dropping unsafe request %llu\n",
++                                         req->r_tid);
+               if (req->r_target_inode)
+                       mapping_set_error(req->r_target_inode->i_mapping, -EIO);
+               if (req->r_unsafe_dir)
+@@ -1791,13 +1806,14 @@ int ceph_iterate_session_caps(struct cep
+                             int (*cb)(struct inode *, int mds, void *),
+                             void *arg)
+ {
++      struct ceph_client *cl = session->s_mdsc->fsc->client;
+       struct list_head *p;
+       struct ceph_cap *cap;
+       struct inode *inode, *last_inode = NULL;
+       struct ceph_cap *old_cap = NULL;
+       int ret;
+-      dout("iterate_session_caps %p mds%d\n", session, session->s_mds);
++      doutc(cl, "%p mds%d\n", session, session->s_mds);
+       spin_lock(&session->s_cap_lock);
+       p = session->s_caps.next;
+       while (p != &session->s_caps) {
+@@ -1828,8 +1844,7 @@ int ceph_iterate_session_caps(struct cep
+               spin_lock(&session->s_cap_lock);
+               p = p->next;
+               if (!cap->ci) {
+-                      dout("iterate_session_caps  finishing cap %p removal\n",
+-                           cap);
++                      doutc(cl, "finishing cap %p removal\n", cap);
+                       BUG_ON(cap->session != session);
+                       cap->session = NULL;
+                       list_del_init(&cap->session_caps);
+@@ -1858,6 +1873,7 @@ out:
+ static int remove_session_caps_cb(struct inode *inode, int mds, void *arg)
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       bool invalidate = false;
+       struct ceph_cap *cap;
+       int iputs = 0;
+@@ -1865,8 +1881,8 @@ static int remove_session_caps_cb(struct
+       spin_lock(&ci->i_ceph_lock);
+       cap = __get_cap_for_mds(ci, mds);
+       if (cap) {
+-              dout(" removing cap %p, ci is %p, inode is %p\n",
+-                   cap, ci, &ci->netfs.inode);
++              doutc(cl, " removing cap %p, ci is %p, inode is %p\n",
++                    cap, ci, &ci->netfs.inode);
+               iputs = ceph_purge_inode_cap(inode, cap, &invalidate);
+       }
+@@ -1890,7 +1906,7 @@ static void remove_session_caps(struct c
+       struct super_block *sb = fsc->sb;
+       LIST_HEAD(dispose);
+-      dout("remove_session_caps on %p\n", session);
++      doutc(fsc->client, "on %p\n", session);
+       ceph_iterate_session_caps(session, remove_session_caps_cb, fsc);
+       wake_up_all(&fsc->mdsc->cap_flushing_wq);
+@@ -1971,7 +1987,9 @@ static int wake_up_session_cb(struct ino
+ static void wake_up_session_caps(struct ceph_mds_session *session, int ev)
+ {
+-      dout("wake_up_session_caps %p mds%d\n", session, session->s_mds);
++      struct ceph_client *cl = session->s_mdsc->fsc->client;
++
++      doutc(cl, "session %p mds%d\n", session, session->s_mds);
+       ceph_iterate_session_caps(session, wake_up_session_cb,
+                                 (void *)(unsigned long)ev);
+ }
+@@ -1985,25 +2003,26 @@ static void wake_up_session_caps(struct
+ static int send_renew_caps(struct ceph_mds_client *mdsc,
+                          struct ceph_mds_session *session)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_msg *msg;
+       int state;
+       if (time_after_eq(jiffies, session->s_cap_ttl) &&
+           time_after_eq(session->s_cap_ttl, session->s_renew_requested))
+-              pr_info("mds%d caps stale\n", session->s_mds);
++              pr_info_client(cl, "mds%d caps stale\n", session->s_mds);
+       session->s_renew_requested = jiffies;
+       /* do not try to renew caps until a recovering mds has reconnected
+        * with its clients. */
+       state = ceph_mdsmap_get_state(mdsc->mdsmap, session->s_mds);
+       if (state < CEPH_MDS_STATE_RECONNECT) {
+-              dout("send_renew_caps ignoring mds%d (%s)\n",
+-                   session->s_mds, ceph_mds_state_name(state));
++              doutc(cl, "ignoring mds%d (%s)\n", session->s_mds,
++                    ceph_mds_state_name(state));
+               return 0;
+       }
+-      dout("send_renew_caps to mds%d (%s)\n", session->s_mds,
+-              ceph_mds_state_name(state));
++      doutc(cl, "to mds%d (%s)\n", session->s_mds,
++            ceph_mds_state_name(state));
+       msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_RENEWCAPS,
+                                     ++session->s_renew_seq);
+       if (!msg)
+@@ -2015,10 +2034,11 @@ static int send_renew_caps(struct ceph_m
+ static int send_flushmsg_ack(struct ceph_mds_client *mdsc,
+                            struct ceph_mds_session *session, u64 seq)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_msg *msg;
+-      dout("send_flushmsg_ack to mds%d (%s)s seq %lld\n",
+-           session->s_mds, ceph_session_state_name(session->s_state), seq);
++      doutc(cl, "to mds%d (%s)s seq %lld\n", session->s_mds,
++            ceph_session_state_name(session->s_state), seq);
+       msg = ceph_create_session_msg(CEPH_SESSION_FLUSHMSG_ACK, seq);
+       if (!msg)
+               return -ENOMEM;
+@@ -2035,6 +2055,7 @@ static int send_flushmsg_ack(struct ceph
+ static void renewed_caps(struct ceph_mds_client *mdsc,
+                        struct ceph_mds_session *session, int is_renew)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int was_stale;
+       int wake = 0;
+@@ -2046,15 +2067,17 @@ static void renewed_caps(struct ceph_mds
+       if (was_stale) {
+               if (time_before(jiffies, session->s_cap_ttl)) {
+-                      pr_info("mds%d caps renewed\n", session->s_mds);
++                      pr_info_client(cl, "mds%d caps renewed\n",
++                                     session->s_mds);
+                       wake = 1;
+               } else {
+-                      pr_info("mds%d caps still stale\n", session->s_mds);
++                      pr_info_client(cl, "mds%d caps still stale\n",
++                                     session->s_mds);
+               }
+       }
+-      dout("renewed_caps mds%d ttl now %lu, was %s, now %s\n",
+-           session->s_mds, session->s_cap_ttl, was_stale ? "stale" : "fresh",
+-           time_before(jiffies, session->s_cap_ttl) ? "stale" : "fresh");
++      doutc(cl, "mds%d ttl now %lu, was %s, now %s\n", session->s_mds,
++            session->s_cap_ttl, was_stale ? "stale" : "fresh",
++            time_before(jiffies, session->s_cap_ttl) ? "stale" : "fresh");
+       spin_unlock(&session->s_cap_lock);
+       if (wake)
+@@ -2066,11 +2089,11 @@ static void renewed_caps(struct ceph_mds
+  */
+ static int request_close_session(struct ceph_mds_session *session)
+ {
++      struct ceph_client *cl = session->s_mdsc->fsc->client;
+       struct ceph_msg *msg;
+-      dout("request_close_session mds%d state %s seq %lld\n",
+-           session->s_mds, ceph_session_state_name(session->s_state),
+-           session->s_seq);
++      doutc(cl, "mds%d state %s seq %lld\n", session->s_mds,
++            ceph_session_state_name(session->s_state), session->s_seq);
+       msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_CLOSE,
+                                     session->s_seq);
+       if (!msg)
+@@ -2127,6 +2150,7 @@ out:
+ static int trim_caps_cb(struct inode *inode, int mds, void *arg)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       int *remaining = arg;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       int used, wanted, oissued, mine;
+@@ -2146,9 +2170,10 @@ static int trim_caps_cb(struct inode *in
+       wanted = __ceph_caps_file_wanted(ci);
+       oissued = __ceph_caps_issued_other(ci, cap);
+-      dout("trim_caps_cb %p cap %p mine %s oissued %s used %s wanted %s\n",
+-           inode, cap, ceph_cap_string(mine), ceph_cap_string(oissued),
+-           ceph_cap_string(used), ceph_cap_string(wanted));
++      doutc(cl, "%p %llx.%llx cap %p mine %s oissued %s used %s wanted %s\n",
++            inode, ceph_vinop(inode), cap, ceph_cap_string(mine),
++            ceph_cap_string(oissued), ceph_cap_string(used),
++            ceph_cap_string(wanted));
+       if (cap == ci->i_auth_cap) {
+               if (ci->i_dirty_caps || ci->i_flushing_caps ||
+                   !list_empty(&ci->i_cap_snaps))
+@@ -2188,8 +2213,8 @@ static int trim_caps_cb(struct inode *in
+                       count = atomic_read(&inode->i_count);
+                       if (count == 1)
+                               (*remaining)--;
+-                      dout("trim_caps_cb %p cap %p pruned, count now %d\n",
+-                           inode, cap, count);
++                      doutc(cl, "%p %llx.%llx cap %p pruned, count now %d\n",
++                            inode, ceph_vinop(inode), cap, count);
+               } else {
+                       dput(dentry);
+               }
+@@ -2208,17 +2233,18 @@ int ceph_trim_caps(struct ceph_mds_clien
+                  struct ceph_mds_session *session,
+                  int max_caps)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int trim_caps = session->s_nr_caps - max_caps;
+-      dout("trim_caps mds%d start: %d / %d, trim %d\n",
+-           session->s_mds, session->s_nr_caps, max_caps, trim_caps);
++      doutc(cl, "mds%d start: %d / %d, trim %d\n", session->s_mds,
++            session->s_nr_caps, max_caps, trim_caps);
+       if (trim_caps > 0) {
+               int remaining = trim_caps;
+               ceph_iterate_session_caps(session, trim_caps_cb, &remaining);
+-              dout("trim_caps mds%d done: %d / %d, trimmed %d\n",
+-                   session->s_mds, session->s_nr_caps, max_caps,
+-                      trim_caps - remaining);
++              doutc(cl, "mds%d done: %d / %d, trimmed %d\n",
++                    session->s_mds, session->s_nr_caps, max_caps,
++                    trim_caps - remaining);
+       }
+       ceph_flush_cap_releases(mdsc, session);
+@@ -2228,6 +2254,7 @@ int ceph_trim_caps(struct ceph_mds_clien
+ static int check_caps_flush(struct ceph_mds_client *mdsc,
+                           u64 want_flush_tid)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int ret = 1;
+       spin_lock(&mdsc->cap_dirty_lock);
+@@ -2236,8 +2263,8 @@ static int check_caps_flush(struct ceph_
+                       list_first_entry(&mdsc->cap_flush_list,
+                                        struct ceph_cap_flush, g_list);
+               if (cf->tid <= want_flush_tid) {
+-                      dout("check_caps_flush still flushing tid "
+-                           "%llu <= %llu\n", cf->tid, want_flush_tid);
++                      doutc(cl, "still flushing tid %llu <= %llu\n",
++                            cf->tid, want_flush_tid);
+                       ret = 0;
+               }
+       }
+@@ -2253,12 +2280,14 @@ static int check_caps_flush(struct ceph_
+ static void wait_caps_flush(struct ceph_mds_client *mdsc,
+                           u64 want_flush_tid)
+ {
+-      dout("check_caps_flush want %llu\n", want_flush_tid);
++      struct ceph_client *cl = mdsc->fsc->client;
++
++      doutc(cl, "want %llu\n", want_flush_tid);
+       wait_event(mdsc->cap_flushing_wq,
+                  check_caps_flush(mdsc, want_flush_tid));
+-      dout("check_caps_flush ok, flushed thru %llu\n", want_flush_tid);
++      doutc(cl, "ok, flushed thru %llu\n", want_flush_tid);
+ }
+ /*
+@@ -2267,6 +2296,7 @@ static void wait_caps_flush(struct ceph_
+ static void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
+                                  struct ceph_mds_session *session)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_msg *msg = NULL;
+       struct ceph_mds_cap_release *head;
+       struct ceph_mds_cap_item *item;
+@@ -2325,7 +2355,7 @@ again:
+                       msg->front.iov_len += sizeof(*cap_barrier);
+                       msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
+-                      dout("send_cap_releases mds%d %p\n", session->s_mds, msg);
++                      doutc(cl, "mds%d %p\n", session->s_mds, msg);
+                       ceph_con_send(&session->s_con, msg);
+                       msg = NULL;
+               }
+@@ -2345,13 +2375,13 @@ again:
+               msg->front.iov_len += sizeof(*cap_barrier);
+               msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
+-              dout("send_cap_releases mds%d %p\n", session->s_mds, msg);
++              doutc(cl, "mds%d %p\n", session->s_mds, msg);
+               ceph_con_send(&session->s_con, msg);
+       }
+       return;
+ out_err:
+-      pr_err("send_cap_releases mds%d, failed to allocate message\n",
+-              session->s_mds);
++      pr_err_client(cl, "mds%d, failed to allocate message\n",
++                    session->s_mds);
+       spin_lock(&session->s_cap_lock);
+       list_splice(&tmp_list, &session->s_cap_releases);
+       session->s_num_cap_releases += num_cap_releases;
+@@ -2374,16 +2404,17 @@ static void ceph_cap_release_work(struct
+ void ceph_flush_cap_releases(struct ceph_mds_client *mdsc,
+                            struct ceph_mds_session *session)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       if (mdsc->stopping)
+               return;
+       ceph_get_mds_session(session);
+       if (queue_work(mdsc->fsc->cap_wq,
+                      &session->s_cap_release_work)) {
+-              dout("cap release work queued\n");
++              doutc(cl, "cap release work queued\n");
+       } else {
+               ceph_put_mds_session(session);
+-              dout("failed to queue cap release work\n");
++              doutc(cl, "failed to queue cap release work\n");
+       }
+ }
+@@ -2411,13 +2442,14 @@ static void ceph_cap_reclaim_work(struct
+ void ceph_queue_cap_reclaim_work(struct ceph_mds_client *mdsc)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       if (mdsc->stopping)
+               return;
+         if (queue_work(mdsc->fsc->cap_wq, &mdsc->cap_reclaim_work)) {
+-                dout("caps reclaim work queued\n");
++                doutc(cl, "caps reclaim work queued\n");
+         } else {
+-                dout("failed to queue caps release work\n");
++                doutc(cl, "failed to queue caps release work\n");
+         }
+ }
+@@ -2612,6 +2644,7 @@ static u8 *get_fscrypt_altname(const str
+ char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry,
+                          int *plen, u64 *pbase, int for_wire)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct dentry *cur;
+       struct inode *inode;
+       char *path;
+@@ -2637,8 +2670,7 @@ retry:
+               spin_lock(&cur->d_lock);
+               inode = d_inode(cur);
+               if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
+-                      dout("build_path path+%d: %p SNAPDIR\n",
+-                           pos, cur);
++                      doutc(cl, "path+%d: %p SNAPDIR\n", pos, cur);
+                       spin_unlock(&cur->d_lock);
+                       parent = dget_parent(cur);
+               } else if (for_wire && inode && dentry != cur &&
+@@ -2725,8 +2757,8 @@ retry:
+       *pbase = base;
+       *plen = PATH_MAX - 1 - pos;
+-      dout("build_path on %p %d built %llx '%.*s'\n",
+-           dentry, d_count(dentry), base, *plen, path + pos);
++      doutc(cl, "on %p %d built %llx '%.*s'\n", dentry, d_count(dentry),
++            base, *plen, path + pos);
+       return path + pos;
+ }
+@@ -2789,22 +2821,22 @@ static int set_request_path_attr(struct
+                                int *pathlen, u64 *ino, bool *freepath,
+                                bool parent_locked)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int r = 0;
+       if (rinode) {
+               r = build_inode_path(rinode, ppath, pathlen, ino, freepath);
+-              dout(" inode %p %llx.%llx\n", rinode, ceph_ino(rinode),
+-                   ceph_snap(rinode));
++              doutc(cl, " inode %p %llx.%llx\n", rinode, ceph_ino(rinode),
++                    ceph_snap(rinode));
+       } else if (rdentry) {
+               r = build_dentry_path(mdsc, rdentry, rdiri, ppath, pathlen, ino,
+                                       freepath, parent_locked);
+-              dout(" dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen,
+-                   *ppath);
++              doutc(cl, " dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen, *ppath);
+       } else if (rpath || rino) {
+               *ino = rino;
+               *ppath = rpath;
+               *pathlen = rpath ? strlen(rpath) : 0;
+-              dout(" path %.*s\n", *pathlen, rpath);
++              doutc(cl, " path %.*s\n", *pathlen, rpath);
+       }
+       return r;
+@@ -3105,6 +3137,7 @@ static int __prepare_send_request(struct
+ {
+       int mds = session->s_mds;
+       struct ceph_mds_client *mdsc = session->s_mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request_head_legacy *lhead;
+       struct ceph_mds_request_head *nhead;
+       struct ceph_msg *msg;
+@@ -3123,8 +3156,8 @@ static int __prepare_send_request(struct
+              old_max_retry = 1 << (old_max_retry * BITS_PER_BYTE);
+              if ((old_version && req->r_attempts >= old_max_retry) ||
+                  ((uint32_t)req->r_attempts >= U32_MAX)) {
+-                      pr_warn_ratelimited("%s request tid %llu seq overflow\n",
+-                                          __func__, req->r_tid);
++                      pr_warn_ratelimited_client(cl, "request tid %llu seq overflow\n",
++                                                 req->r_tid);
+                       return -EMULTIHOP;
+              }
+       }
+@@ -3139,8 +3172,8 @@ static int __prepare_send_request(struct
+               else
+                       req->r_sent_on_mseq = -1;
+       }
+-      dout("%s %p tid %lld %s (attempt %d)\n", __func__, req,
+-           req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts);
++      doutc(cl, "%p tid %lld %s (attempt %d)\n", req, req->r_tid,
++            ceph_mds_op_name(req->r_op), req->r_attempts);
+       if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) {
+               void *p;
+@@ -3208,7 +3241,7 @@ static int __prepare_send_request(struct
+               nhead->ext_num_retry = cpu_to_le32(req->r_attempts - 1);
+       }
+-      dout(" r_parent = %p\n", req->r_parent);
++      doutc(cl, " r_parent = %p\n", req->r_parent);
+       return 0;
+ }
+@@ -3236,6 +3269,7 @@ static int __send_request(struct ceph_md
+ static void __do_request(struct ceph_mds_client *mdsc,
+                       struct ceph_mds_request *req)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_session *session = NULL;
+       int mds = -1;
+       int err = 0;
+@@ -3248,29 +3282,29 @@ static void __do_request(struct ceph_mds
+       }
+       if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO) {
+-              dout("do_request metadata corrupted\n");
++              doutc(cl, "metadata corrupted\n");
+               err = -EIO;
+               goto finish;
+       }
+       if (req->r_timeout &&
+           time_after_eq(jiffies, req->r_started + req->r_timeout)) {
+-              dout("do_request timed out\n");
++              doutc(cl, "timed out\n");
+               err = -ETIMEDOUT;
+               goto finish;
+       }
+       if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
+-              dout("do_request forced umount\n");
++              doutc(cl, "forced umount\n");
+               err = -EIO;
+               goto finish;
+       }
+       if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_MOUNTING) {
+               if (mdsc->mdsmap_err) {
+                       err = mdsc->mdsmap_err;
+-                      dout("do_request mdsmap err %d\n", err);
++                      doutc(cl, "mdsmap err %d\n", err);
+                       goto finish;
+               }
+               if (mdsc->mdsmap->m_epoch == 0) {
+-                      dout("do_request no mdsmap, waiting for map\n");
++                      doutc(cl, "no mdsmap, waiting for map\n");
+                       list_add(&req->r_wait, &mdsc->waiting_for_map);
+                       return;
+               }
+@@ -3291,7 +3325,7 @@ static void __do_request(struct ceph_mds
+                       err = -EJUKEBOX;
+                       goto finish;
+               }
+-              dout("do_request no mds or not active, waiting for map\n");
++              doutc(cl, "no mds or not active, waiting for map\n");
+               list_add(&req->r_wait, &mdsc->waiting_for_map);
+               return;
+       }
+@@ -3307,8 +3341,8 @@ static void __do_request(struct ceph_mds
+       }
+       req->r_session = ceph_get_mds_session(session);
+-      dout("do_request mds%d session %p state %s\n", mds, session,
+-           ceph_session_state_name(session->s_state));
++      doutc(cl, "mds%d session %p state %s\n", mds, session,
++            ceph_session_state_name(session->s_state));
+       /*
+        * The old ceph will crash the MDSs when see unknown OPs
+@@ -3399,8 +3433,8 @@ static void __do_request(struct ceph_mds
+               spin_lock(&ci->i_ceph_lock);
+               cap = ci->i_auth_cap;
+               if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE && mds != cap->mds) {
+-                      dout("do_request session changed for auth cap %d -> %d\n",
+-                           cap->session->s_mds, session->s_mds);
++                      doutc(cl, "session changed for auth cap %d -> %d\n",
++                            cap->session->s_mds, session->s_mds);
+                       /* Remove the auth cap from old session */
+                       spin_lock(&cap->session->s_cap_lock);
+@@ -3427,7 +3461,7 @@ out_session:
+       ceph_put_mds_session(session);
+ finish:
+       if (err) {
+-              dout("__do_request early error %d\n", err);
++              doutc(cl, "early error %d\n", err);
+               req->r_err = err;
+               complete_request(mdsc, req);
+               __unregister_request(mdsc, req);
+@@ -3441,6 +3475,7 @@ finish:
+ static void __wake_requests(struct ceph_mds_client *mdsc,
+                           struct list_head *head)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       LIST_HEAD(tmp_list);
+@@ -3450,7 +3485,8 @@ static void __wake_requests(struct ceph_
+               req = list_entry(tmp_list.next,
+                                struct ceph_mds_request, r_wait);
+               list_del_init(&req->r_wait);
+-              dout(" wake request %p tid %llu\n", req, req->r_tid);
++              doutc(cl, " wake request %p tid %llu\n", req,
++                    req->r_tid);
+               __do_request(mdsc, req);
+       }
+ }
+@@ -3461,10 +3497,11 @@ static void __wake_requests(struct ceph_
+  */
+ static void kick_requests(struct ceph_mds_client *mdsc, int mds)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       struct rb_node *p = rb_first(&mdsc->request_tree);
+-      dout("kick_requests mds%d\n", mds);
++      doutc(cl, "kick_requests mds%d\n", mds);
+       while (p) {
+               req = rb_entry(p, struct ceph_mds_request, r_node);
+               p = rb_next(p);
+@@ -3474,7 +3511,7 @@ static void kick_requests(struct ceph_md
+                       continue; /* only new requests */
+               if (req->r_session &&
+                   req->r_session->s_mds == mds) {
+-                      dout(" kicking tid %llu\n", req->r_tid);
++                      doutc(cl, " kicking tid %llu\n", req->r_tid);
+                       list_del_init(&req->r_wait);
+                       __do_request(mdsc, req);
+               }
+@@ -3484,6 +3521,7 @@ static void kick_requests(struct ceph_md
+ int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
+                             struct ceph_mds_request *req)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int err = 0;
+       /* take CAP_PIN refs for r_inode, r_parent, r_old_dentry */
+@@ -3505,8 +3543,7 @@ int ceph_mdsc_submit_request(struct ceph
+       if (req->r_inode) {
+               err = ceph_wait_on_async_create(req->r_inode);
+               if (err) {
+-                      dout("%s: wait for async create returned: %d\n",
+-                           __func__, err);
++                      doutc(cl, "wait for async create returned: %d\n", err);
+                       return err;
+               }
+       }
+@@ -3514,13 +3551,12 @@ int ceph_mdsc_submit_request(struct ceph
+       if (!err && req->r_old_inode) {
+               err = ceph_wait_on_async_create(req->r_old_inode);
+               if (err) {
+-                      dout("%s: wait for async create returned: %d\n",
+-                           __func__, err);
++                      doutc(cl, "wait for async create returned: %d\n", err);
+                       return err;
+               }
+       }
+-      dout("submit_request on %p for inode %p\n", req, dir);
++      doutc(cl, "submit_request on %p for inode %p\n", req, dir);
+       mutex_lock(&mdsc->mutex);
+       __register_request(mdsc, req, dir);
+       __do_request(mdsc, req);
+@@ -3533,10 +3569,11 @@ int ceph_mdsc_wait_request(struct ceph_m
+                          struct ceph_mds_request *req,
+                          ceph_mds_request_wait_callback_t wait_func)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int err;
+       /* wait */
+-      dout("do_request waiting\n");
++      doutc(cl, "do_request waiting\n");
+       if (wait_func) {
+               err = wait_func(mdsc, req);
+       } else {
+@@ -3550,14 +3587,14 @@ int ceph_mdsc_wait_request(struct ceph_m
+               else
+                       err = timeleft;  /* killed */
+       }
+-      dout("do_request waited, got %d\n", err);
++      doutc(cl, "do_request waited, got %d\n", err);
+       mutex_lock(&mdsc->mutex);
+       /* only abort if we didn't race with a real reply */
+       if (test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
+               err = le32_to_cpu(req->r_reply_info.head->result);
+       } else if (err < 0) {
+-              dout("aborted request %lld with %d\n", req->r_tid, err);
++              doutc(cl, "aborted request %lld with %d\n", req->r_tid, err);
+               /*
+                * ensure we aren't running concurrently with
+@@ -3588,15 +3625,16 @@ int ceph_mdsc_do_request(struct ceph_mds
+                        struct inode *dir,
+                        struct ceph_mds_request *req)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       int err;
+-      dout("do_request on %p\n", req);
++      doutc(cl, "do_request on %p\n", req);
+       /* issue */
+       err = ceph_mdsc_submit_request(mdsc, dir, req);
+       if (!err)
+               err = ceph_mdsc_wait_request(mdsc, req, NULL);
+-      dout("do_request %p done, result %d\n", req, err);
++      doutc(cl, "do_request %p done, result %d\n", req, err);
+       return err;
+ }
+@@ -3608,8 +3646,10 @@ void ceph_invalidate_dir_request(struct
+ {
+       struct inode *dir = req->r_parent;
+       struct inode *old_dir = req->r_old_dentry_dir;
++      struct ceph_client *cl = req->r_mdsc->fsc->client;
+-      dout("invalidate_dir_request %p %p (complete, lease(s))\n", dir, old_dir);
++      doutc(cl, "invalidate_dir_request %p %p (complete, lease(s))\n",
++            dir, old_dir);
+       ceph_dir_clear_complete(dir);
+       if (old_dir)
+@@ -3630,6 +3670,7 @@ void ceph_invalidate_dir_request(struct
+ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
+ {
+       struct ceph_mds_client *mdsc = session->s_mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       struct ceph_mds_reply_head *head = msg->front.iov_base;
+       struct ceph_mds_reply_info_parsed *rinfo;  /* parsed reply info */
+@@ -3640,7 +3681,7 @@ static void handle_reply(struct ceph_mds
+       bool close_sessions = false;
+       if (msg->front.iov_len < sizeof(*head)) {
+-              pr_err("mdsc_handle_reply got corrupt (short) reply\n");
++              pr_err_client(cl, "got corrupt (short) reply\n");
+               ceph_msg_dump(msg);
+               return;
+       }
+@@ -3650,17 +3691,17 @@ static void handle_reply(struct ceph_mds
+       mutex_lock(&mdsc->mutex);
+       req = lookup_get_request(mdsc, tid);
+       if (!req) {
+-              dout("handle_reply on unknown tid %llu\n", tid);
++              doutc(cl, "on unknown tid %llu\n", tid);
+               mutex_unlock(&mdsc->mutex);
+               return;
+       }
+-      dout("handle_reply %p\n", req);
++      doutc(cl, "handle_reply %p\n", req);
+       /* correct session? */
+       if (req->r_session != session) {
+-              pr_err("mdsc_handle_reply got %llu on session mds%d"
+-                     " not mds%d\n", tid, session->s_mds,
+-                     req->r_session ? req->r_session->s_mds : -1);
++              pr_err_client(cl, "got %llu on session mds%d not mds%d\n",
++                            tid, session->s_mds,
++                            req->r_session ? req->r_session->s_mds : -1);
+               mutex_unlock(&mdsc->mutex);
+               goto out;
+       }
+@@ -3668,14 +3709,14 @@ static void handle_reply(struct ceph_mds
+       /* dup? */
+       if ((test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags) && !head->safe) ||
+           (test_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags) && head->safe)) {
+-              pr_warn("got a dup %s reply on %llu from mds%d\n",
+-                         head->safe ? "safe" : "unsafe", tid, mds);
++              pr_warn_client(cl, "got a dup %s reply on %llu from mds%d\n",
++                             head->safe ? "safe" : "unsafe", tid, mds);
+               mutex_unlock(&mdsc->mutex);
+               goto out;
+       }
+       if (test_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags)) {
+-              pr_warn("got unsafe after safe on %llu from mds%d\n",
+-                         tid, mds);
++              pr_warn_client(cl, "got unsafe after safe on %llu from mds%d\n",
++                             tid, mds);
+               mutex_unlock(&mdsc->mutex);
+               goto out;
+       }
+@@ -3698,7 +3739,7 @@ static void handle_reply(struct ceph_mds
+                        * response.  And even if it did, there is nothing
+                        * useful we could do with a revised return value.
+                        */
+-                      dout("got safe reply %llu, mds%d\n", tid, mds);
++                      doutc(cl, "got safe reply %llu, mds%d\n", tid, mds);
+                       mutex_unlock(&mdsc->mutex);
+                       goto out;
+@@ -3708,7 +3749,7 @@ static void handle_reply(struct ceph_mds
+               list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe);
+       }
+-      dout("handle_reply tid %lld result %d\n", tid, result);
++      doutc(cl, "tid %lld result %d\n", tid, result);
+       if (test_bit(CEPHFS_FEATURE_REPLY_ENCODING, &session->s_features))
+               err = parse_reply_info(session, msg, req, (u64)-1);
+       else
+@@ -3748,7 +3789,8 @@ static void handle_reply(struct ceph_mds
+       mutex_lock(&session->s_mutex);
+       if (err < 0) {
+-              pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid);
++              pr_err_client(cl, "got corrupt reply mds%d(tid:%lld)\n",
++                            mds, tid);
+               ceph_msg_dump(msg);
+               goto out_err;
+       }
+@@ -3812,7 +3854,7 @@ out_err:
+                       set_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags);
+               }
+       } else {
+-              dout("reply arrived after request %lld was aborted\n", tid);
++              doutc(cl, "reply arrived after request %lld was aborted\n", tid);
+       }
+       mutex_unlock(&mdsc->mutex);
+@@ -3841,6 +3883,7 @@ static void handle_forward(struct ceph_m
+                          struct ceph_mds_session *session,
+                          struct ceph_msg *msg)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req;
+       u64 tid = le64_to_cpu(msg->hdr.tid);
+       u32 next_mds;
+@@ -3858,12 +3901,12 @@ static void handle_forward(struct ceph_m
+       req = lookup_get_request(mdsc, tid);
+       if (!req) {
+               mutex_unlock(&mdsc->mutex);
+-              dout("forward tid %llu to mds%d - req dne\n", tid, next_mds);
++              doutc(cl, "forward tid %llu to mds%d - req dne\n", tid, next_mds);
+               return;  /* dup reply? */
+       }
+       if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) {
+-              dout("forward tid %llu aborted, unregistering\n", tid);
++              doutc(cl, "forward tid %llu aborted, unregistering\n", tid);
+               __unregister_request(mdsc, req);
+       } else if (fwd_seq <= req->r_num_fwd || (uint32_t)fwd_seq >= U32_MAX) {
+               /*
+@@ -3879,10 +3922,11 @@ static void handle_forward(struct ceph_m
+               set_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags);
+               mutex_unlock(&req->r_fill_mutex);
+               aborted = true;
+-              pr_warn_ratelimited("forward tid %llu seq overflow\n", tid);
++              pr_warn_ratelimited_client(cl, "forward tid %llu seq overflow\n",
++                                         tid);
+       } else {
+               /* resend. forward race not possible; mds would drop */
+-              dout("forward tid %llu to mds%d (we resend)\n", tid, next_mds);
++              doutc(cl, "forward tid %llu to mds%d (we resend)\n", tid, next_mds);
+               BUG_ON(req->r_err);
+               BUG_ON(test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags));
+               req->r_attempts = 0;
+@@ -3900,7 +3944,7 @@ static void handle_forward(struct ceph_m
+       return;
+ bad:
+-      pr_err("mdsc_handle_forward decode error err=%d\n", err);
++      pr_err_client(cl, "decode error err=%d\n", err);
+       ceph_msg_dump(msg);
+ }
+@@ -3939,6 +3983,7 @@ static void handle_session(struct ceph_m
+                          struct ceph_msg *msg)
+ {
+       struct ceph_mds_client *mdsc = session->s_mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       int mds = session->s_mds;
+       int msg_version = le16_to_cpu(msg->hdr.version);
+       void *p = msg->front.iov_base;
+@@ -3986,7 +4031,8 @@ static void handle_session(struct ceph_m
+               /* version >= 5, flags   */
+               ceph_decode_32_safe(&p, end, flags, bad);
+               if (flags & CEPH_SESSION_BLOCKLISTED) {
+-                      pr_warn("mds%d session blocklisted\n", session->s_mds);
++                      pr_warn_client(cl, "mds%d session blocklisted\n",
++                                     session->s_mds);
+                       blocklisted = true;
+               }
+       }
+@@ -4002,23 +4048,25 @@ static void handle_session(struct ceph_m
+       mutex_lock(&session->s_mutex);
+-      dout("handle_session mds%d %s %p state %s seq %llu\n",
+-           mds, ceph_session_op_name(op), session,
+-           ceph_session_state_name(session->s_state), seq);
++      doutc(cl, "mds%d %s %p state %s seq %llu\n", mds,
++            ceph_session_op_name(op), session,
++            ceph_session_state_name(session->s_state), seq);
+       if (session->s_state == CEPH_MDS_SESSION_HUNG) {
+               session->s_state = CEPH_MDS_SESSION_OPEN;
+-              pr_info("mds%d came back\n", session->s_mds);
++              pr_info_client(cl, "mds%d came back\n", session->s_mds);
+       }
+       switch (op) {
+       case CEPH_SESSION_OPEN:
+               if (session->s_state == CEPH_MDS_SESSION_RECONNECTING)
+-                      pr_info("mds%d reconnect success\n", session->s_mds);
++                      pr_info_client(cl, "mds%d reconnect success\n",
++                                     session->s_mds);
+               session->s_features = features;
+               if (session->s_state == CEPH_MDS_SESSION_OPEN) {
+-                      pr_notice("mds%d is already opened\n", session->s_mds);
++                      pr_notice_client(cl, "mds%d is already opened\n",
++                                       session->s_mds);
+               } else {
+                       session->s_state = CEPH_MDS_SESSION_OPEN;
+                       renewed_caps(mdsc, session, 0);
+@@ -4047,7 +4095,8 @@ static void handle_session(struct ceph_m
+       case CEPH_SESSION_CLOSE:
+               if (session->s_state == CEPH_MDS_SESSION_RECONNECTING)
+-                      pr_info("mds%d reconnect denied\n", session->s_mds);
++                      pr_info_client(cl, "mds%d reconnect denied\n",
++                                     session->s_mds);
+               session->s_state = CEPH_MDS_SESSION_CLOSED;
+               cleanup_session_requests(mdsc, session);
+               remove_session_caps(session);
+@@ -4056,8 +4105,8 @@ static void handle_session(struct ceph_m
+               break;
+       case CEPH_SESSION_STALE:
+-              pr_info("mds%d caps went stale, renewing\n",
+-                      session->s_mds);
++              pr_info_client(cl, "mds%d caps went stale, renewing\n",
++                             session->s_mds);
+               atomic_inc(&session->s_cap_gen);
+               session->s_cap_ttl = jiffies - 1;
+               send_renew_caps(mdsc, session);
+@@ -4078,7 +4127,7 @@ static void handle_session(struct ceph_m
+               break;
+       case CEPH_SESSION_FORCE_RO:
+-              dout("force_session_readonly %p\n", session);
++              doutc(cl, "force_session_readonly %p\n", session);
+               spin_lock(&session->s_cap_lock);
+               session->s_readonly = true;
+               spin_unlock(&session->s_cap_lock);
+@@ -4087,7 +4136,8 @@ static void handle_session(struct ceph_m
+       case CEPH_SESSION_REJECT:
+               WARN_ON(session->s_state != CEPH_MDS_SESSION_OPENING);
+-              pr_info("mds%d rejected session\n", session->s_mds);
++              pr_info_client(cl, "mds%d rejected session\n",
++                             session->s_mds);
+               session->s_state = CEPH_MDS_SESSION_REJECTED;
+               cleanup_session_requests(mdsc, session);
+               remove_session_caps(session);
+@@ -4097,7 +4147,7 @@ static void handle_session(struct ceph_m
+               break;
+       default:
+-              pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds);
++              pr_err_client(cl, "bad op %d mds%d\n", op, mds);
+               WARN_ON(1);
+       }
+@@ -4114,30 +4164,32 @@ static void handle_session(struct ceph_m
+       return;
+ bad:
+-      pr_err("mdsc_handle_session corrupt message mds%d len %d\n", mds,
+-             (int)msg->front.iov_len);
++      pr_err_client(cl, "corrupt message mds%d len %d\n", mds,
++                    (int)msg->front.iov_len);
+       ceph_msg_dump(msg);
+       return;
+ }
+ void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req)
+ {
++      struct ceph_client *cl = req->r_mdsc->fsc->client;
+       int dcaps;
+       dcaps = xchg(&req->r_dir_caps, 0);
+       if (dcaps) {
+-              dout("releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
++              doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
+               ceph_put_cap_refs(ceph_inode(req->r_parent), dcaps);
+       }
+ }
+ void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req)
+ {
++      struct ceph_client *cl = req->r_mdsc->fsc->client;
+       int dcaps;
+       dcaps = xchg(&req->r_dir_caps, 0);
+       if (dcaps) {
+-              dout("releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
++              doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
+               ceph_put_cap_refs_no_check_caps(ceph_inode(req->r_parent),
+                                               dcaps);
+       }
+@@ -4152,7 +4204,7 @@ static void replay_unsafe_requests(struc
+       struct ceph_mds_request *req, *nreq;
+       struct rb_node *p;
+-      dout("replay_unsafe_requests mds%d\n", session->s_mds);
++      doutc(mdsc->fsc->client, "mds%d\n", session->s_mds);
+       mutex_lock(&mdsc->mutex);
+       list_for_each_entry_safe(req, nreq, &session->s_unsafe, r_unsafe_item)
+@@ -4297,6 +4349,7 @@ out_unlock:
+ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       union {
+               struct ceph_mds_cap_reconnect v2;
+               struct ceph_mds_cap_reconnect_v1 v1;
+@@ -4333,9 +4386,9 @@ static int reconnect_caps_cb(struct inod
+               err = 0;
+               goto out_err;
+       }
+-      dout(" adding %p ino %llx.%llx cap %p %lld %s\n",
+-           inode, ceph_vinop(inode), cap, cap->cap_id,
+-           ceph_cap_string(cap->issued));
++      doutc(cl, " adding %p ino %llx.%llx cap %p %lld %s\n", inode,
++            ceph_vinop(inode), cap, cap->cap_id,
++            ceph_cap_string(cap->issued));
+       cap->seq = 0;        /* reset cap seq */
+       cap->issue_seq = 0;  /* and issue_seq */
+@@ -4485,6 +4538,7 @@ static int encode_snap_realms(struct cep
+ {
+       struct rb_node *p;
+       struct ceph_pagelist *pagelist = recon_state->pagelist;
++      struct ceph_client *cl = mdsc->fsc->client;
+       int err = 0;
+       if (recon_state->msg_version >= 4) {
+@@ -4523,8 +4577,8 @@ static int encode_snap_realms(struct cep
+                       ceph_pagelist_encode_32(pagelist, sizeof(sr_rec));
+               }
+-              dout(" adding snap realm %llx seq %lld parent %llx\n",
+-                   realm->ino, realm->seq, realm->parent_ino);
++              doutc(cl, " adding snap realm %llx seq %lld parent %llx\n",
++                    realm->ino, realm->seq, realm->parent_ino);
+               sr_rec.ino = cpu_to_le64(realm->ino);
+               sr_rec.seq = cpu_to_le64(realm->seq);
+               sr_rec.parent = cpu_to_le64(realm->parent_ino);
+@@ -4553,6 +4607,7 @@ fail:
+ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
+                              struct ceph_mds_session *session)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_msg *reply;
+       int mds = session->s_mds;
+       int err = -ENOMEM;
+@@ -4561,7 +4616,7 @@ static void send_mds_reconnect(struct ce
+       };
+       LIST_HEAD(dispose);
+-      pr_info("mds%d reconnect start\n", mds);
++      pr_info_client(cl, "mds%d reconnect start\n", mds);
+       recon_state.pagelist = ceph_pagelist_alloc(GFP_NOFS);
+       if (!recon_state.pagelist)
+@@ -4577,8 +4632,8 @@ static void send_mds_reconnect(struct ce
+       session->s_state = CEPH_MDS_SESSION_RECONNECTING;
+       session->s_seq = 0;
+-      dout("session %p state %s\n", session,
+-           ceph_session_state_name(session->s_state));
++      doutc(cl, "session %p state %s\n", session,
++            ceph_session_state_name(session->s_state));
+       atomic_inc(&session->s_cap_gen);
+@@ -4712,7 +4767,8 @@ fail:
+ fail_nomsg:
+       ceph_pagelist_release(recon_state.pagelist);
+ fail_nopagelist:
+-      pr_err("error %d preparing reconnect for mds%d\n", err, mds);
++      pr_err_client(cl, "error %d preparing reconnect for mds%d\n",
++                    err, mds);
+       return;
+ }
+@@ -4731,9 +4787,9 @@ static void check_new_map(struct ceph_md
+       int oldstate, newstate;
+       struct ceph_mds_session *s;
+       unsigned long targets[DIV_ROUND_UP(CEPH_MAX_MDS, sizeof(unsigned long))] = {0};
++      struct ceph_client *cl = mdsc->fsc->client;
+-      dout("check_new_map new %u old %u\n",
+-           newmap->m_epoch, oldmap->m_epoch);
++      doutc(cl, "new %u old %u\n", newmap->m_epoch, oldmap->m_epoch);
+       if (newmap->m_info) {
+               for (i = 0; i < newmap->possible_max_rank; i++) {
+@@ -4749,12 +4805,12 @@ static void check_new_map(struct ceph_md
+               oldstate = ceph_mdsmap_get_state(oldmap, i);
+               newstate = ceph_mdsmap_get_state(newmap, i);
+-              dout("check_new_map mds%d state %s%s -> %s%s (session %s)\n",
+-                   i, ceph_mds_state_name(oldstate),
+-                   ceph_mdsmap_is_laggy(oldmap, i) ? " (laggy)" : "",
+-                   ceph_mds_state_name(newstate),
+-                   ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "",
+-                   ceph_session_state_name(s->s_state));
++              doutc(cl, "mds%d state %s%s -> %s%s (session %s)\n",
++                    i, ceph_mds_state_name(oldstate),
++                    ceph_mdsmap_is_laggy(oldmap, i) ? " (laggy)" : "",
++                    ceph_mds_state_name(newstate),
++                    ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "",
++                    ceph_session_state_name(s->s_state));
+               if (i >= newmap->possible_max_rank) {
+                       /* force close session for stopped mds */
+@@ -4807,7 +4863,8 @@ static void check_new_map(struct ceph_md
+                   newstate >= CEPH_MDS_STATE_ACTIVE) {
+                       if (oldstate != CEPH_MDS_STATE_CREATING &&
+                           oldstate != CEPH_MDS_STATE_STARTING)
+-                              pr_info("mds%d recovery completed\n", s->s_mds);
++                              pr_info_client(cl, "mds%d recovery completed\n",
++                                             s->s_mds);
+                       kick_requests(mdsc, i);
+                       mutex_unlock(&mdsc->mutex);
+                       mutex_lock(&s->s_mutex);
+@@ -4851,12 +4908,13 @@ static void check_new_map(struct ceph_md
+                       s = __open_export_target_session(mdsc, i);
+                       if (IS_ERR(s)) {
+                               err = PTR_ERR(s);
+-                              pr_err("failed to open export target session, err %d\n",
+-                                     err);
++                              pr_err_client(cl,
++                                            "failed to open export target session, err %d\n",
++                                            err);
+                               continue;
+                       }
+               }
+-              dout("send reconnect to export target mds.%d\n", i);
++              doutc(cl, "send reconnect to export target mds.%d\n", i);
+               mutex_unlock(&mdsc->mutex);
+               send_mds_reconnect(mdsc, s);
+               ceph_put_mds_session(s);
+@@ -4872,8 +4930,7 @@ static void check_new_map(struct ceph_md
+               if (s->s_state == CEPH_MDS_SESSION_OPEN ||
+                   s->s_state == CEPH_MDS_SESSION_HUNG ||
+                   s->s_state == CEPH_MDS_SESSION_CLOSING) {
+-                      dout(" connecting to export targets of laggy mds%d\n",
+-                           i);
++                      doutc(cl, " connecting to export targets of laggy mds%d\n", i);
+                       __open_export_target_sessions(mdsc, s);
+               }
+       }
+@@ -4900,6 +4957,7 @@ static void handle_lease(struct ceph_mds
+                        struct ceph_mds_session *session,
+                        struct ceph_msg *msg)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct super_block *sb = mdsc->fsc->sb;
+       struct inode *inode;
+       struct dentry *parent, *dentry;
+@@ -4911,7 +4969,7 @@ static void handle_lease(struct ceph_mds
+       struct qstr dname;
+       int release = 0;
+-      dout("handle_lease from mds%d\n", mds);
++      doutc(cl, "from mds%d\n", mds);
+       if (!ceph_inc_mds_stopping_blocker(mdsc, session))
+               return;
+@@ -4929,20 +4987,19 @@ static void handle_lease(struct ceph_mds
+       /* lookup inode */
+       inode = ceph_find_inode(sb, vino);
+-      dout("handle_lease %s, ino %llx %p %.*s\n",
+-           ceph_lease_op_name(h->action), vino.ino, inode,
+-           dname.len, dname.name);
++      doutc(cl, "%s, ino %llx %p %.*s\n", ceph_lease_op_name(h->action),
++            vino.ino, inode, dname.len, dname.name);
+       mutex_lock(&session->s_mutex);
+       if (!inode) {
+-              dout("handle_lease no inode %llx\n", vino.ino);
++              doutc(cl, "no inode %llx\n", vino.ino);
+               goto release;
+       }
+       /* dentry */
+       parent = d_find_alias(inode);
+       if (!parent) {
+-              dout("no parent dentry on inode %p\n", inode);
++              doutc(cl, "no parent dentry on inode %p\n", inode);
+               WARN_ON(1);
+               goto release;  /* hrm... */
+       }
+@@ -5002,7 +5059,7 @@ out:
+ bad:
+       ceph_dec_mds_stopping_blocker(mdsc);
+-      pr_err("corrupt lease message\n");
++      pr_err_client(cl, "corrupt lease message\n");
+       ceph_msg_dump(msg);
+ }
+@@ -5010,13 +5067,14 @@ void ceph_mdsc_lease_send_msg(struct cep
+                             struct dentry *dentry, char action,
+                             u32 seq)
+ {
++      struct ceph_client *cl = session->s_mdsc->fsc->client;
+       struct ceph_msg *msg;
+       struct ceph_mds_lease *lease;
+       struct inode *dir;
+       int len = sizeof(*lease) + sizeof(u32) + NAME_MAX;
+-      dout("lease_send_msg identry %p %s to mds%d\n",
+-           dentry, ceph_lease_op_name(action), session->s_mds);
++      doutc(cl, "identry %p %s to mds%d\n", dentry, ceph_lease_op_name(action),
++            session->s_mds);
+       msg = ceph_msg_new(CEPH_MSG_CLIENT_LEASE, len, GFP_NOFS, false);
+       if (!msg)
+@@ -5049,6 +5107,7 @@ static void lock_unlock_session(struct c
+ static void maybe_recover_session(struct ceph_mds_client *mdsc)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_fs_client *fsc = mdsc->fsc;
+       if (!ceph_test_mount_opt(fsc, CLEANRECOVER))
+@@ -5060,17 +5119,19 @@ static void maybe_recover_session(struct
+       if (!READ_ONCE(fsc->blocklisted))
+               return;
+-      pr_info("auto reconnect after blocklisted\n");
++      pr_info_client(cl, "auto reconnect after blocklisted\n");
+       ceph_force_reconnect(fsc->sb);
+ }
+ bool check_session_state(struct ceph_mds_session *s)
+ {
++      struct ceph_client *cl = s->s_mdsc->fsc->client;
++
+       switch (s->s_state) {
+       case CEPH_MDS_SESSION_OPEN:
+               if (s->s_ttl && time_after(jiffies, s->s_ttl)) {
+                       s->s_state = CEPH_MDS_SESSION_HUNG;
+-                      pr_info("mds%d hung\n", s->s_mds);
++                      pr_info_client(cl, "mds%d hung\n", s->s_mds);
+               }
+               break;
+       case CEPH_MDS_SESSION_CLOSING:
+@@ -5090,6 +5151,8 @@ bool check_session_state(struct ceph_mds
+  */
+ void inc_session_sequence(struct ceph_mds_session *s)
+ {
++      struct ceph_client *cl = s->s_mdsc->fsc->client;
++
+       lockdep_assert_held(&s->s_mutex);
+       s->s_seq++;
+@@ -5097,11 +5160,11 @@ void inc_session_sequence(struct ceph_md
+       if (s->s_state == CEPH_MDS_SESSION_CLOSING) {
+               int ret;
+-              dout("resending session close request for mds%d\n", s->s_mds);
++              doutc(cl, "resending session close request for mds%d\n", s->s_mds);
+               ret = request_close_session(s);
+               if (ret < 0)
+-                      pr_err("unable to close session to mds%d: %d\n",
+-                             s->s_mds, ret);
++                      pr_err_client(cl, "unable to close session to mds%d: %d\n",
++                                    s->s_mds, ret);
+       }
+ }
+@@ -5130,7 +5193,7 @@ static void delayed_work(struct work_str
+       int renew_caps;
+       int i;
+-      dout("mdsc delayed_work\n");
++      doutc(mdsc->fsc->client, "mdsc delayed_work\n");
+       if (mdsc->stopping >= CEPH_MDSC_STOPPING_FLUSHED)
+               return;
+@@ -5259,6 +5322,7 @@ err_mdsc:
+  */
+ static void wait_requests(struct ceph_mds_client *mdsc)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_options *opts = mdsc->fsc->client->options;
+       struct ceph_mds_request *req;
+@@ -5266,25 +5330,25 @@ static void wait_requests(struct ceph_md
+       if (__get_oldest_req(mdsc)) {
+               mutex_unlock(&mdsc->mutex);
+-              dout("wait_requests waiting for requests\n");
++              doutc(cl, "waiting for requests\n");
+               wait_for_completion_timeout(&mdsc->safe_umount_waiters,
+                                   ceph_timeout_jiffies(opts->mount_timeout));
+               /* tear down remaining requests */
+               mutex_lock(&mdsc->mutex);
+               while ((req = __get_oldest_req(mdsc))) {
+-                      dout("wait_requests timed out on tid %llu\n",
+-                           req->r_tid);
++                      doutc(cl, "timed out on tid %llu\n", req->r_tid);
+                       list_del_init(&req->r_wait);
+                       __unregister_request(mdsc, req);
+               }
+       }
+       mutex_unlock(&mdsc->mutex);
+-      dout("wait_requests done\n");
++      doutc(cl, "done\n");
+ }
+ void send_flush_mdlog(struct ceph_mds_session *s)
+ {
++      struct ceph_client *cl = s->s_mdsc->fsc->client;
+       struct ceph_msg *msg;
+       /*
+@@ -5294,13 +5358,13 @@ void send_flush_mdlog(struct ceph_mds_se
+               return;
+       mutex_lock(&s->s_mutex);
+-      dout("request mdlog flush to mds%d (%s)s seq %lld\n", s->s_mds,
+-           ceph_session_state_name(s->s_state), s->s_seq);
++      doutc(cl, "request mdlog flush to mds%d (%s)s seq %lld\n",
++            s->s_mds, ceph_session_state_name(s->s_state), s->s_seq);
+       msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_FLUSH_MDLOG,
+                                     s->s_seq);
+       if (!msg) {
+-              pr_err("failed to request mdlog flush to mds%d (%s) seq %lld\n",
+-                     s->s_mds, ceph_session_state_name(s->s_state), s->s_seq);
++              pr_err_client(cl, "failed to request mdlog flush to mds%d (%s) seq %lld\n",
++                            s->s_mds, ceph_session_state_name(s->s_state), s->s_seq);
+       } else {
+               ceph_con_send(&s->s_con, msg);
+       }
+@@ -5313,7 +5377,7 @@ void send_flush_mdlog(struct ceph_mds_se
+  */
+ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
+ {
+-      dout("pre_umount\n");
++      doutc(mdsc->fsc->client, "begin\n");
+       mdsc->stopping = CEPH_MDSC_STOPPING_BEGIN;
+       ceph_mdsc_iterate_sessions(mdsc, send_flush_mdlog, true);
+@@ -5328,6 +5392,7 @@ void ceph_mdsc_pre_umount(struct ceph_md
+       ceph_msgr_flush();
+       ceph_cleanup_quotarealms_inodes(mdsc);
++      doutc(mdsc->fsc->client, "done\n");
+ }
+ /*
+@@ -5336,12 +5401,13 @@ void ceph_mdsc_pre_umount(struct ceph_md
+ static void flush_mdlog_and_wait_mdsc_unsafe_requests(struct ceph_mds_client *mdsc,
+                                                u64 want_tid)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_request *req = NULL, *nextreq;
+       struct ceph_mds_session *last_session = NULL;
+       struct rb_node *n;
+       mutex_lock(&mdsc->mutex);
+-      dout("%s want %lld\n", __func__, want_tid);
++      doutc(cl, "want %lld\n", want_tid);
+ restart:
+       req = __get_oldest_req(mdsc);
+       while (req && req->r_tid <= want_tid) {
+@@ -5375,8 +5441,8 @@ restart:
+                       } else {
+                               ceph_put_mds_session(s);
+                       }
+-                      dout("%s wait on %llu (want %llu)\n", __func__,
+-                           req->r_tid, want_tid);
++                      doutc(cl, "wait on %llu (want %llu)\n",
++                            req->r_tid, want_tid);
+                       wait_for_completion(&req->r_safe_completion);
+                       mutex_lock(&mdsc->mutex);
+@@ -5394,17 +5460,18 @@ restart:
+       }
+       mutex_unlock(&mdsc->mutex);
+       ceph_put_mds_session(last_session);
+-      dout("%s done\n", __func__);
++      doutc(cl, "done\n");
+ }
+ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       u64 want_tid, want_flush;
+       if (READ_ONCE(mdsc->fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN)
+               return;
+-      dout("sync\n");
++      doutc(cl, "sync\n");
+       mutex_lock(&mdsc->mutex);
+       want_tid = mdsc->last_tid;
+       mutex_unlock(&mdsc->mutex);
+@@ -5420,8 +5487,7 @@ void ceph_mdsc_sync(struct ceph_mds_clie
+       }
+       spin_unlock(&mdsc->cap_dirty_lock);
+-      dout("sync want tid %lld flush_seq %lld\n",
+-           want_tid, want_flush);
++      doutc(cl, "sync want tid %lld flush_seq %lld\n", want_tid, want_flush);
+       flush_mdlog_and_wait_mdsc_unsafe_requests(mdsc, want_tid);
+       wait_caps_flush(mdsc, want_flush);
+@@ -5443,11 +5509,12 @@ static bool done_closing_sessions(struct
+ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
+ {
+       struct ceph_options *opts = mdsc->fsc->client->options;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_session *session;
+       int i;
+       int skipped = 0;
+-      dout("close_sessions\n");
++      doutc(cl, "begin\n");
+       /* close sessions */
+       mutex_lock(&mdsc->mutex);
+@@ -5465,7 +5532,7 @@ void ceph_mdsc_close_sessions(struct cep
+       }
+       mutex_unlock(&mdsc->mutex);
+-      dout("waiting for sessions to close\n");
++      doutc(cl, "waiting for sessions to close\n");
+       wait_event_timeout(mdsc->session_close_wq,
+                          done_closing_sessions(mdsc, skipped),
+                          ceph_timeout_jiffies(opts->mount_timeout));
+@@ -5493,7 +5560,7 @@ void ceph_mdsc_close_sessions(struct cep
+       cancel_work_sync(&mdsc->cap_reclaim_work);
+       cancel_delayed_work_sync(&mdsc->delayed_work); /* cancel timer */
+-      dout("stopped\n");
++      doutc(cl, "done\n");
+ }
+ void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
+@@ -5501,7 +5568,7 @@ void ceph_mdsc_force_umount(struct ceph_
+       struct ceph_mds_session *session;
+       int mds;
+-      dout("force umount\n");
++      doutc(mdsc->fsc->client, "force umount\n");
+       mutex_lock(&mdsc->mutex);
+       for (mds = 0; mds < mdsc->max_sessions; mds++) {
+@@ -5532,7 +5599,7 @@ void ceph_mdsc_force_umount(struct ceph_
+ static void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
+ {
+-      dout("stop\n");
++      doutc(mdsc->fsc->client, "stop\n");
+       /*
+        * Make sure the delayed work stopped before releasing
+        * the resources.
+@@ -5553,7 +5620,7 @@ static void ceph_mdsc_stop(struct ceph_m
+ void ceph_mdsc_destroy(struct ceph_fs_client *fsc)
+ {
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+-      dout("mdsc_destroy %p\n", mdsc);
++      doutc(fsc->client, "%p\n", mdsc);
+       if (!mdsc)
+               return;
+@@ -5567,12 +5634,13 @@ void ceph_mdsc_destroy(struct ceph_fs_cl
+       fsc->mdsc = NULL;
+       kfree(mdsc);
+-      dout("mdsc_destroy %p done\n", mdsc);
++      doutc(fsc->client, "%p done\n", mdsc);
+ }
+ void ceph_mdsc_handle_fsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
+ {
+       struct ceph_fs_client *fsc = mdsc->fsc;
++      struct ceph_client *cl = fsc->client;
+       const char *mds_namespace = fsc->mount_options->mds_namespace;
+       void *p = msg->front.iov_base;
+       void *end = p + msg->front.iov_len;
+@@ -5584,7 +5652,7 @@ void ceph_mdsc_handle_fsmap(struct ceph_
+       ceph_decode_need(&p, end, sizeof(u32), bad);
+       epoch = ceph_decode_32(&p);
+-      dout("handle_fsmap epoch %u\n", epoch);
++      doutc(cl, "epoch %u\n", epoch);
+       /* struct_v, struct_cv, map_len, epoch, legacy_client_fscid */
+       ceph_decode_skip_n(&p, end, 2 + sizeof(u32) * 3, bad);
+@@ -5629,7 +5697,8 @@ void ceph_mdsc_handle_fsmap(struct ceph_
+       return;
+ bad:
+-      pr_err("error decoding fsmap %d. Shutting down mount.\n", err);
++      pr_err_client(cl, "error decoding fsmap %d. Shutting down mount.\n",
++                    err);
+       ceph_umount_begin(mdsc->fsc->sb);
+       ceph_msg_dump(msg);
+ err_out:
+@@ -5644,6 +5713,7 @@ err_out:
+  */
+ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       u32 epoch;
+       u32 maplen;
+       void *p = msg->front.iov_base;
+@@ -5658,13 +5728,12 @@ void ceph_mdsc_handle_mdsmap(struct ceph
+               return;
+       epoch = ceph_decode_32(&p);
+       maplen = ceph_decode_32(&p);
+-      dout("handle_map epoch %u len %d\n", epoch, (int)maplen);
++      doutc(cl, "epoch %u len %d\n", epoch, (int)maplen);
+       /* do we need it? */
+       mutex_lock(&mdsc->mutex);
+       if (mdsc->mdsmap && epoch <= mdsc->mdsmap->m_epoch) {
+-              dout("handle_map epoch %u <= our %u\n",
+-                   epoch, mdsc->mdsmap->m_epoch);
++              doutc(cl, "epoch %u <= our %u\n", epoch, mdsc->mdsmap->m_epoch);
+               mutex_unlock(&mdsc->mutex);
+               return;
+       }
+@@ -5698,7 +5767,8 @@ void ceph_mdsc_handle_mdsmap(struct ceph
+ bad_unlock:
+       mutex_unlock(&mdsc->mutex);
+ bad:
+-      pr_err("error decoding mdsmap %d. Shutting down mount.\n", err);
++      pr_err_client(cl, "error decoding mdsmap %d. Shutting down mount.\n",
++                    err);
+       ceph_umount_begin(mdsc->fsc->sb);
+       ceph_msg_dump(msg);
+       return;
+@@ -5729,7 +5799,8 @@ static void mds_peer_reset(struct ceph_c
+       struct ceph_mds_session *s = con->private;
+       struct ceph_mds_client *mdsc = s->s_mdsc;
+-      pr_warn("mds%d closed our session\n", s->s_mds);
++      pr_warn_client(mdsc->fsc->client, "mds%d closed our session\n",
++                     s->s_mds);
+       if (READ_ONCE(mdsc->fsc->mount_state) != CEPH_MOUNT_FENCE_IO)
+               send_mds_reconnect(mdsc, s);
+ }
+@@ -5738,6 +5809,7 @@ static void mds_dispatch(struct ceph_con
+ {
+       struct ceph_mds_session *s = con->private;
+       struct ceph_mds_client *mdsc = s->s_mdsc;
++      struct ceph_client *cl = mdsc->fsc->client;
+       int type = le16_to_cpu(msg->hdr.type);
+       mutex_lock(&mdsc->mutex);
+@@ -5777,8 +5849,8 @@ static void mds_dispatch(struct ceph_con
+               break;
+       default:
+-              pr_err("received unknown message type %d %s\n", type,
+-                     ceph_msg_type_name(type));
++              pr_err_client(cl, "received unknown message type %d %s\n",
++                            type, ceph_msg_type_name(type));
+       }
+ out:
+       ceph_msg_put(msg);
+--- a/fs/ceph/mdsmap.c
++++ b/fs/ceph/mdsmap.c
+@@ -11,6 +11,7 @@
+ #include <linux/ceph/messenger.h>
+ #include <linux/ceph/decode.h>
++#include "mds_client.h"
+ #include "super.h"
+ #define CEPH_MDS_IS_READY(i, ignore_laggy) \
+@@ -117,6 +118,7 @@ bad:
+ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p,
+                                      void *end, bool msgr2)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mdsmap *m;
+       const void *start = *p;
+       int i, j, n;
+@@ -234,20 +236,18 @@ struct ceph_mdsmap *ceph_mdsmap_decode(s
+                       *p = info_end;
+               }
+-              dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s%s\n",
+-                   i+1, n, global_id, mds, inc,
+-                   ceph_pr_addr(&addr),
+-                   ceph_mds_state_name(state),
+-                   laggy ? "(laggy)" : "");
++              doutc(cl, "%d/%d %lld mds%d.%d %s %s%s\n", i+1, n, global_id,
++                    mds, inc, ceph_pr_addr(&addr),
++                    ceph_mds_state_name(state), laggy ? "(laggy)" : "");
+               if (mds < 0 || mds >= m->possible_max_rank) {
+-                      pr_warn("mdsmap_decode got incorrect mds(%d)\n", mds);
++                      pr_warn_client(cl, "got incorrect mds(%d)\n", mds);
+                       continue;
+               }
+               if (state <= 0) {
+-                      dout("mdsmap_decode got incorrect state(%s)\n",
+-                           ceph_mds_state_name(state));
++                      doutc(cl, "got incorrect state(%s)\n",
++                            ceph_mds_state_name(state));
+                       continue;
+               }
+@@ -387,16 +387,16 @@ struct ceph_mdsmap *ceph_mdsmap_decode(s
+               ceph_decode_64_safe(p, end, m->m_max_xattr_size, bad_ext);
+       }
+ bad_ext:
+-      dout("mdsmap_decode m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n",
+-           !!m->m_enabled, !!m->m_damaged, m->m_num_laggy);
++      doutc(cl, "m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n",
++            !!m->m_enabled, !!m->m_damaged, m->m_num_laggy);
+       *p = end;
+-      dout("mdsmap_decode success epoch %u\n", m->m_epoch);
++      doutc(cl, "success epoch %u\n", m->m_epoch);
+       return m;
+ nomem:
+       err = -ENOMEM;
+       goto out_err;
+ corrupt:
+-      pr_err("corrupt mdsmap\n");
++      pr_err_client(cl, "corrupt mdsmap\n");
+       print_hex_dump(KERN_DEBUG, "mdsmap: ",
+                      DUMP_PREFIX_OFFSET, 16, 1,
+                      start, end - start, true);
+--- a/fs/ceph/metric.c
++++ b/fs/ceph/metric.c
+@@ -31,6 +31,7 @@ static bool ceph_mdsc_send_metrics(struc
+       struct ceph_client_metric *m = &mdsc->metric;
+       u64 nr_caps = atomic64_read(&m->total_caps);
+       u32 header_len = sizeof(struct ceph_metric_header);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_msg *msg;
+       s64 sum;
+       s32 items = 0;
+@@ -51,8 +52,8 @@ static bool ceph_mdsc_send_metrics(struc
+       msg = ceph_msg_new(CEPH_MSG_CLIENT_METRICS, len, GFP_NOFS, true);
+       if (!msg) {
+-              pr_err("send metrics to mds%d, failed to allocate message\n",
+-                     s->s_mds);
++              pr_err_client(cl, "to mds%d, failed to allocate message\n",
++                            s->s_mds);
+               return false;
+       }
+--- a/fs/ceph/quota.c
++++ b/fs/ceph/quota.c
+@@ -43,6 +43,7 @@ void ceph_handle_quota(struct ceph_mds_c
+ {
+       struct super_block *sb = mdsc->fsc->sb;
+       struct ceph_mds_quota *h = msg->front.iov_base;
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_vino vino;
+       struct inode *inode;
+       struct ceph_inode_info *ci;
+@@ -51,8 +52,8 @@ void ceph_handle_quota(struct ceph_mds_c
+               return;
+       if (msg->front.iov_len < sizeof(*h)) {
+-              pr_err("%s corrupt message mds%d len %d\n", __func__,
+-                     session->s_mds, (int)msg->front.iov_len);
++              pr_err_client(cl, "corrupt message mds%d len %d\n",
++                            session->s_mds, (int)msg->front.iov_len);
+               ceph_msg_dump(msg);
+               goto out;
+       }
+@@ -62,7 +63,7 @@ void ceph_handle_quota(struct ceph_mds_c
+       vino.snap = CEPH_NOSNAP;
+       inode = ceph_find_inode(sb, vino);
+       if (!inode) {
+-              pr_warn("Failed to find inode %llu\n", vino.ino);
++              pr_warn_client(cl, "failed to find inode %llx\n", vino.ino);
+               goto out;
+       }
+       ci = ceph_inode(inode);
+@@ -85,6 +86,7 @@ find_quotarealm_inode(struct ceph_mds_cl
+ {
+       struct ceph_quotarealm_inode *qri = NULL;
+       struct rb_node **node, *parent = NULL;
++      struct ceph_client *cl = mdsc->fsc->client;
+       mutex_lock(&mdsc->quotarealms_inodes_mutex);
+       node = &(mdsc->quotarealms_inodes.rb_node);
+@@ -110,7 +112,7 @@ find_quotarealm_inode(struct ceph_mds_cl
+                       rb_link_node(&qri->node, parent, node);
+                       rb_insert_color(&qri->node, &mdsc->quotarealms_inodes);
+               } else
+-                      pr_warn("Failed to alloc quotarealms_inode\n");
++                      pr_warn_client(cl, "Failed to alloc quotarealms_inode\n");
+       }
+       mutex_unlock(&mdsc->quotarealms_inodes_mutex);
+@@ -129,6 +131,7 @@ static struct inode *lookup_quotarealm_i
+                                            struct super_block *sb,
+                                            struct ceph_snap_realm *realm)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_quotarealm_inode *qri;
+       struct inode *in;
+@@ -161,8 +164,8 @@ static struct inode *lookup_quotarealm_i
+       }
+       if (IS_ERR(in)) {
+-              dout("Can't lookup inode %llx (err: %ld)\n",
+-                   realm->ino, PTR_ERR(in));
++              doutc(cl, "Can't lookup inode %llx (err: %ld)\n", realm->ino,
++                    PTR_ERR(in));
+               qri->timeout = jiffies + msecs_to_jiffies(60 * 1000); /* XXX */
+       } else {
+               qri->timeout = 0;
+@@ -212,6 +215,7 @@ static int get_quota_realm(struct ceph_m
+                          enum quota_get_realm which_quota,
+                          struct ceph_snap_realm **realmp, bool retry)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *ci = NULL;
+       struct ceph_snap_realm *realm, *next;
+       struct inode *in;
+@@ -227,8 +231,9 @@ restart:
+       if (realm)
+               ceph_get_snap_realm(mdsc, realm);
+       else
+-              pr_err_ratelimited("get_quota_realm: ino (%llx.%llx) "
+-                                 "null i_snap_realm\n", ceph_vinop(inode));
++              pr_err_ratelimited_client(cl,
++                              "%p %llx.%llx null i_snap_realm\n",
++                              inode, ceph_vinop(inode));
+       while (realm) {
+               bool has_inode;
+@@ -322,6 +327,7 @@ static bool check_quota_exceeded(struct
+                                loff_t delta)
+ {
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *ci;
+       struct ceph_snap_realm *realm, *next;
+       struct inode *in;
+@@ -337,8 +343,9 @@ restart:
+       if (realm)
+               ceph_get_snap_realm(mdsc, realm);
+       else
+-              pr_err_ratelimited("check_quota_exceeded: ino (%llx.%llx) "
+-                                 "null i_snap_realm\n", ceph_vinop(inode));
++              pr_err_ratelimited_client(cl,
++                              "%p %llx.%llx null i_snap_realm\n",
++                              inode, ceph_vinop(inode));
+       while (realm) {
+               bool has_inode;
+@@ -388,7 +395,7 @@ restart:
+                       break;
+               default:
+                       /* Shouldn't happen */
+-                      pr_warn("Invalid quota check op (%d)\n", op);
++                      pr_warn_client(cl, "Invalid quota check op (%d)\n", op);
+                       exceeded = true; /* Just break the loop */
+               }
+               iput(in);
+--- a/fs/ceph/snap.c
++++ b/fs/ceph/snap.c
+@@ -138,7 +138,7 @@ static struct ceph_snap_realm *ceph_crea
+       __insert_snap_realm(&mdsc->snap_realms, realm);
+       mdsc->num_snap_realms++;
+-      dout("%s %llx %p\n", __func__, realm->ino, realm);
++      doutc(mdsc->fsc->client, "%llx %p\n", realm->ino, realm);
+       return realm;
+ }
+@@ -150,6 +150,7 @@ static struct ceph_snap_realm *ceph_crea
+ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,
+                                                  u64 ino)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct rb_node *n = mdsc->snap_realms.rb_node;
+       struct ceph_snap_realm *r;
+@@ -162,7 +163,7 @@ static struct ceph_snap_realm *__lookup_
+               else if (ino > r->ino)
+                       n = n->rb_right;
+               else {
+-                      dout("%s %llx %p\n", __func__, r->ino, r);
++                      doutc(cl, "%llx %p\n", r->ino, r);
+                       return r;
+               }
+       }
+@@ -188,9 +189,10 @@ static void __put_snap_realm(struct ceph
+ static void __destroy_snap_realm(struct ceph_mds_client *mdsc,
+                                struct ceph_snap_realm *realm)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       lockdep_assert_held_write(&mdsc->snap_rwsem);
+-      dout("%s %p %llx\n", __func__, realm, realm->ino);
++      doutc(cl, "%p %llx\n", realm, realm->ino);
+       rb_erase(&realm->node, &mdsc->snap_realms);
+       mdsc->num_snap_realms--;
+@@ -290,6 +292,7 @@ static int adjust_snap_realm_parent(stru
+                                   struct ceph_snap_realm *realm,
+                                   u64 parentino)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_snap_realm *parent;
+       lockdep_assert_held_write(&mdsc->snap_rwsem);
+@@ -303,8 +306,8 @@ static int adjust_snap_realm_parent(stru
+               if (IS_ERR(parent))
+                       return PTR_ERR(parent);
+       }
+-      dout("%s %llx %p: %llx %p -> %llx %p\n", __func__, realm->ino,
+-           realm, realm->parent_ino, realm->parent, parentino, parent);
++      doutc(cl, "%llx %p: %llx %p -> %llx %p\n", realm->ino, realm,
++            realm->parent_ino, realm->parent, parentino, parent);
+       if (realm->parent) {
+               list_del_init(&realm->child_item);
+               ceph_put_snap_realm(mdsc, realm->parent);
+@@ -334,6 +337,7 @@ static int build_snap_context(struct cep
+                             struct list_head *realm_queue,
+                             struct list_head *dirty_realms)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_snap_realm *parent = realm->parent;
+       struct ceph_snap_context *snapc;
+       int err = 0;
+@@ -361,10 +365,10 @@ static int build_snap_context(struct cep
+           realm->cached_context->seq == realm->seq &&
+           (!parent ||
+            realm->cached_context->seq >= parent->cached_context->seq)) {
+-              dout("%s %llx %p: %p seq %lld (%u snaps) (unchanged)\n",
+-                   __func__, realm->ino, realm, realm->cached_context,
+-                   realm->cached_context->seq,
+-                   (unsigned int)realm->cached_context->num_snaps);
++              doutc(cl, "%llx %p: %p seq %lld (%u snaps) (unchanged)\n",
++                    realm->ino, realm, realm->cached_context,
++                    realm->cached_context->seq,
++                    (unsigned int)realm->cached_context->num_snaps);
+               return 0;
+       }
+@@ -401,8 +405,8 @@ static int build_snap_context(struct cep
+       sort(snapc->snaps, num, sizeof(u64), cmpu64_rev, NULL);
+       snapc->num_snaps = num;
+-      dout("%s %llx %p: %p seq %lld (%u snaps)\n", __func__, realm->ino,
+-           realm, snapc, snapc->seq, (unsigned int) snapc->num_snaps);
++      doutc(cl, "%llx %p: %p seq %lld (%u snaps)\n", realm->ino, realm,
++            snapc, snapc->seq, (unsigned int) snapc->num_snaps);
+       ceph_put_snap_context(realm->cached_context);
+       realm->cached_context = snapc;
+@@ -419,7 +423,7 @@ fail:
+               ceph_put_snap_context(realm->cached_context);
+               realm->cached_context = NULL;
+       }
+-      pr_err("%s %llx %p fail %d\n", __func__, realm->ino, realm, err);
++      pr_err_client(cl, "%llx %p fail %d\n", realm->ino, realm, err);
+       return err;
+ }
+@@ -430,6 +434,7 @@ static void rebuild_snap_realms(struct c
+                               struct ceph_snap_realm *realm,
+                               struct list_head *dirty_realms)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       LIST_HEAD(realm_queue);
+       int last = 0;
+       bool skip = false;
+@@ -455,8 +460,8 @@ static void rebuild_snap_realms(struct c
+               last = build_snap_context(mdsc, _realm, &realm_queue,
+                                         dirty_realms);
+-              dout("%s %llx %p, %s\n", __func__, _realm->ino, _realm,
+-                   last > 0 ? "is deferred" : !last ? "succeeded" : "failed");
++              doutc(cl, "%llx %p, %s\n", realm->ino, realm,
++                    last > 0 ? "is deferred" : !last ? "succeeded" : "failed");
+               /* is any child in the list ? */
+               list_for_each_entry(child, &_realm->children, child_item) {
+@@ -526,6 +531,7 @@ static void ceph_queue_cap_snap(struct c
+                               struct ceph_cap_snap **pcapsnap)
+ {
+       struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_snap_context *old_snapc, *new_snapc;
+       struct ceph_cap_snap *capsnap = *pcapsnap;
+       struct ceph_buffer *old_blob = NULL;
+@@ -551,14 +557,14 @@ static void ceph_queue_cap_snap(struct c
+                  as no new writes are allowed to start when pending, so any
+                  writes in progress now were started before the previous
+                  cap_snap.  lucky us. */
+-              dout("%s %p %llx.%llx already pending\n",
+-                   __func__, inode, ceph_vinop(inode));
++              doutc(cl, "%p %llx.%llx already pending\n", inode,
++                    ceph_vinop(inode));
+               goto update_snapc;
+       }
+       if (ci->i_wrbuffer_ref_head == 0 &&
+           !(dirty & (CEPH_CAP_ANY_EXCL|CEPH_CAP_FILE_WR))) {
+-              dout("%s %p %llx.%llx nothing dirty|writing\n",
+-                   __func__, inode, ceph_vinop(inode));
++              doutc(cl, "%p %llx.%llx nothing dirty|writing\n", inode,
++                    ceph_vinop(inode));
+               goto update_snapc;
+       }
+@@ -578,15 +584,15 @@ static void ceph_queue_cap_snap(struct c
+       } else {
+               if (!(used & CEPH_CAP_FILE_WR) &&
+                   ci->i_wrbuffer_ref_head == 0) {
+-                      dout("%s %p %llx.%llx no new_snap|dirty_page|writing\n",
+-                           __func__, inode, ceph_vinop(inode));
++                      doutc(cl, "%p %llx.%llx no new_snap|dirty_page|writing\n",
++                            inode, ceph_vinop(inode));
+                       goto update_snapc;
+               }
+       }
+-      dout("%s %p %llx.%llx cap_snap %p queuing under %p %s %s\n",
+-           __func__, inode, ceph_vinop(inode), capsnap, old_snapc,
+-           ceph_cap_string(dirty), capsnap->need_flush ? "" : "no_flush");
++      doutc(cl, "%p %llx.%llx cap_snap %p queuing under %p %s %s\n",
++            inode, ceph_vinop(inode), capsnap, old_snapc,
++            ceph_cap_string(dirty), capsnap->need_flush ? "" : "no_flush");
+       ihold(inode);
+       capsnap->follows = old_snapc->seq;
+@@ -618,9 +624,9 @@ static void ceph_queue_cap_snap(struct c
+       list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps);
+       if (used & CEPH_CAP_FILE_WR) {
+-              dout("%s %p %llx.%llx cap_snap %p snapc %p seq %llu used WR,"
+-                   " now pending\n", __func__, inode, ceph_vinop(inode),
+-                   capsnap, old_snapc, old_snapc->seq);
++              doutc(cl, "%p %llx.%llx cap_snap %p snapc %p seq %llu used WR,"
++                    " now pending\n", inode, ceph_vinop(inode), capsnap,
++                    old_snapc, old_snapc->seq);
+               capsnap->writing = 1;
+       } else {
+               /* note mtime, size NOW. */
+@@ -637,7 +643,7 @@ update_snapc:
+               ci->i_head_snapc = NULL;
+       } else {
+               ci->i_head_snapc = ceph_get_snap_context(new_snapc);
+-              dout(" new snapc is %p\n", new_snapc);
++              doutc(cl, " new snapc is %p\n", new_snapc);
+       }
+       spin_unlock(&ci->i_ceph_lock);
+@@ -658,6 +664,7 @@ int __ceph_finish_cap_snap(struct ceph_i
+ {
+       struct inode *inode = &ci->netfs.inode;
+       struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
++      struct ceph_client *cl = mdsc->fsc->client;
+       BUG_ON(capsnap->writing);
+       capsnap->size = i_size_read(inode);
+@@ -670,11 +677,12 @@ int __ceph_finish_cap_snap(struct ceph_i
+       capsnap->truncate_size = ci->i_truncate_size;
+       capsnap->truncate_seq = ci->i_truncate_seq;
+       if (capsnap->dirty_pages) {
+-              dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu "
+-                   "still has %d dirty pages\n", __func__, inode,
+-                   ceph_vinop(inode), capsnap, capsnap->context,
+-                   capsnap->context->seq, ceph_cap_string(capsnap->dirty),
+-                   capsnap->size, capsnap->dirty_pages);
++              doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s "
++                    "s=%llu still has %d dirty pages\n", inode,
++                    ceph_vinop(inode), capsnap, capsnap->context,
++                    capsnap->context->seq,
++                    ceph_cap_string(capsnap->dirty),
++                    capsnap->size, capsnap->dirty_pages);
+               return 0;
+       }
+@@ -683,20 +691,20 @@ int __ceph_finish_cap_snap(struct ceph_i
+        * And trigger to flush the buffer immediately.
+        */
+       if (ci->i_wrbuffer_ref) {
+-              dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu "
+-                   "used WRBUFFER, delaying\n", __func__, inode,
+-                   ceph_vinop(inode), capsnap, capsnap->context,
+-                   capsnap->context->seq, ceph_cap_string(capsnap->dirty),
+-                   capsnap->size);
++              doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s "
++                    "s=%llu used WRBUFFER, delaying\n", inode,
++                    ceph_vinop(inode), capsnap, capsnap->context,
++                    capsnap->context->seq, ceph_cap_string(capsnap->dirty),
++                    capsnap->size);
+               ceph_queue_writeback(inode);
+               return 0;
+       }
+       ci->i_ceph_flags |= CEPH_I_FLUSH_SNAPS;
+-      dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu\n",
+-           __func__, inode, ceph_vinop(inode), capsnap, capsnap->context,
+-           capsnap->context->seq, ceph_cap_string(capsnap->dirty),
+-           capsnap->size);
++      doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu\n",
++            inode, ceph_vinop(inode), capsnap, capsnap->context,
++            capsnap->context->seq, ceph_cap_string(capsnap->dirty),
++            capsnap->size);
+       spin_lock(&mdsc->snap_flush_lock);
+       if (list_empty(&ci->i_snap_flush_item)) {
+@@ -714,11 +722,12 @@ int __ceph_finish_cap_snap(struct ceph_i
+ static void queue_realm_cap_snaps(struct ceph_mds_client *mdsc,
+                                 struct ceph_snap_realm *realm)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *ci;
+       struct inode *lastinode = NULL;
+       struct ceph_cap_snap *capsnap = NULL;
+-      dout("%s %p %llx inode\n", __func__, realm, realm->ino);
++      doutc(cl, "%p %llx inode\n", realm, realm->ino);
+       spin_lock(&realm->inodes_with_caps_lock);
+       list_for_each_entry(ci, &realm->inodes_with_caps, i_snap_realm_item) {
+@@ -737,8 +746,9 @@ static void queue_realm_cap_snaps(struct
+               if (!capsnap) {
+                       capsnap = kmem_cache_zalloc(ceph_cap_snap_cachep, GFP_NOFS);
+                       if (!capsnap) {
+-                              pr_err("ENOMEM allocating ceph_cap_snap on %p\n",
+-                                     inode);
++                              pr_err_client(cl,
++                                      "ENOMEM allocating ceph_cap_snap on %p\n",
++                                      inode);
+                               return;
+                       }
+               }
+@@ -756,7 +766,7 @@ static void queue_realm_cap_snaps(struct
+       if (capsnap)
+               kmem_cache_free(ceph_cap_snap_cachep, capsnap);
+-      dout("%s %p %llx done\n", __func__, realm, realm->ino);
++      doutc(cl, "%p %llx done\n", realm, realm->ino);
+ }
+ /*
+@@ -770,6 +780,7 @@ int ceph_update_snap_trace(struct ceph_m
+                          void *p, void *e, bool deletion,
+                          struct ceph_snap_realm **realm_ret)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_mds_snap_realm *ri;    /* encoded */
+       __le64 *snaps;                     /* encoded */
+       __le64 *prior_parent_snaps;        /* encoded */
+@@ -784,7 +795,7 @@ int ceph_update_snap_trace(struct ceph_m
+       lockdep_assert_held_write(&mdsc->snap_rwsem);
+-      dout("%s deletion=%d\n", __func__, deletion);
++      doutc(cl, "deletion=%d\n", deletion);
+ more:
+       realm = NULL;
+       rebuild_snapcs = 0;
+@@ -814,8 +825,8 @@ more:
+       rebuild_snapcs += err;
+       if (le64_to_cpu(ri->seq) > realm->seq) {
+-              dout("%s updating %llx %p %lld -> %lld\n", __func__,
+-                   realm->ino, realm, realm->seq, le64_to_cpu(ri->seq));
++              doutc(cl, "updating %llx %p %lld -> %lld\n", realm->ino,
++                    realm, realm->seq, le64_to_cpu(ri->seq));
+               /* update realm parameters, snap lists */
+               realm->seq = le64_to_cpu(ri->seq);
+               realm->created = le64_to_cpu(ri->created);
+@@ -838,16 +849,16 @@ more:
+               rebuild_snapcs = 1;
+       } else if (!realm->cached_context) {
+-              dout("%s %llx %p seq %lld new\n", __func__,
+-                   realm->ino, realm, realm->seq);
++              doutc(cl, "%llx %p seq %lld new\n", realm->ino, realm,
++                    realm->seq);
+               rebuild_snapcs = 1;
+       } else {
+-              dout("%s %llx %p seq %lld unchanged\n", __func__,
+-                   realm->ino, realm, realm->seq);
++              doutc(cl, "%llx %p seq %lld unchanged\n", realm->ino, realm,
++                    realm->seq);
+       }
+-      dout("done with %llx %p, rebuild_snapcs=%d, %p %p\n", realm->ino,
+-           realm, rebuild_snapcs, p, e);
++      doutc(cl, "done with %llx %p, rebuild_snapcs=%d, %p %p\n", realm->ino,
++            realm, rebuild_snapcs, p, e);
+       /*
+        * this will always track the uppest parent realm from which
+@@ -895,7 +906,7 @@ fail:
+               ceph_put_snap_realm(mdsc, realm);
+       if (first_realm)
+               ceph_put_snap_realm(mdsc, first_realm);
+-      pr_err("%s error %d\n", __func__, err);
++      pr_err_client(cl, "error %d\n", err);
+       /*
+        * When receiving a corrupted snap trace we don't know what
+@@ -909,11 +920,12 @@ fail:
+       WRITE_ONCE(mdsc->fsc->mount_state, CEPH_MOUNT_FENCE_IO);
+       ret = ceph_monc_blocklist_add(&client->monc, &client->msgr.inst.addr);
+       if (ret)
+-              pr_err("%s failed to blocklist %s: %d\n", __func__,
+-                     ceph_pr_addr(&client->msgr.inst.addr), ret);
++              pr_err_client(cl, "failed to blocklist %s: %d\n",
++                            ceph_pr_addr(&client->msgr.inst.addr), ret);
+-      WARN(1, "%s: %s%sdo remount to continue%s",
+-           __func__, ret ? "" : ceph_pr_addr(&client->msgr.inst.addr),
++      WARN(1, "[client.%lld] %s %s%sdo remount to continue%s",
++           client->monc.auth->global_id, __func__,
++           ret ? "" : ceph_pr_addr(&client->msgr.inst.addr),
+            ret ? "" : " was blocklisted, ",
+            err == -EIO ? " after corrupted snaptrace is fixed" : "");
+@@ -929,11 +941,12 @@ fail:
+  */
+ static void flush_snaps(struct ceph_mds_client *mdsc)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_inode_info *ci;
+       struct inode *inode;
+       struct ceph_mds_session *session = NULL;
+-      dout("%s\n", __func__);
++      doutc(cl, "begin\n");
+       spin_lock(&mdsc->snap_flush_lock);
+       while (!list_empty(&mdsc->snap_flush_list)) {
+               ci = list_first_entry(&mdsc->snap_flush_list,
+@@ -948,7 +961,7 @@ static void flush_snaps(struct ceph_mds_
+       spin_unlock(&mdsc->snap_flush_lock);
+       ceph_put_mds_session(session);
+-      dout("%s done\n", __func__);
++      doutc(cl, "done\n");
+ }
+ /**
+@@ -1004,6 +1017,7 @@ void ceph_handle_snap(struct ceph_mds_cl
+                     struct ceph_mds_session *session,
+                     struct ceph_msg *msg)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct super_block *sb = mdsc->fsc->sb;
+       int mds = session->s_mds;
+       u64 split;
+@@ -1034,8 +1048,8 @@ void ceph_handle_snap(struct ceph_mds_cl
+       trace_len = le32_to_cpu(h->trace_len);
+       p += sizeof(*h);
+-      dout("%s from mds%d op %s split %llx tracelen %d\n", __func__,
+-           mds, ceph_snap_op_name(op), split, trace_len);
++      doutc(cl, "from mds%d op %s split %llx tracelen %d\n", mds,
++            ceph_snap_op_name(op), split, trace_len);
+       down_write(&mdsc->snap_rwsem);
+       locked_rwsem = 1;
+@@ -1066,7 +1080,7 @@ void ceph_handle_snap(struct ceph_mds_cl
+                               goto out;
+               }
+-              dout("splitting snap_realm %llx %p\n", realm->ino, realm);
++              doutc(cl, "splitting snap_realm %llx %p\n", realm->ino, realm);
+               for (i = 0; i < num_split_inos; i++) {
+                       struct ceph_vino vino = {
+                               .ino = le64_to_cpu(split_inos[i]),
+@@ -1091,13 +1105,13 @@ void ceph_handle_snap(struct ceph_mds_cl
+                        */
+                       if (ci->i_snap_realm->created >
+                           le64_to_cpu(ri->created)) {
+-                              dout(" leaving %p %llx.%llx in newer realm %llx %p\n",
+-                                   inode, ceph_vinop(inode), ci->i_snap_realm->ino,
+-                                   ci->i_snap_realm);
++                              doutc(cl, " leaving %p %llx.%llx in newer realm %llx %p\n",
++                                    inode, ceph_vinop(inode), ci->i_snap_realm->ino,
++                                    ci->i_snap_realm);
+                               goto skip_inode;
+                       }
+-                      dout(" will move %p %llx.%llx to split realm %llx %p\n",
+-                           inode, ceph_vinop(inode), realm->ino, realm);
++                      doutc(cl, " will move %p %llx.%llx to split realm %llx %p\n",
++                            inode, ceph_vinop(inode), realm->ino, realm);
+                       ceph_get_snap_realm(mdsc, realm);
+                       ceph_change_snap_realm(inode, realm);
+@@ -1158,7 +1172,7 @@ skip_inode:
+       return;
+ bad:
+-      pr_err("%s corrupt snap message from mds%d\n", __func__, mds);
++      pr_err_client(cl, "corrupt snap message from mds%d\n", mds);
+       ceph_msg_dump(msg);
+ out:
+       if (locked_rwsem)
+@@ -1174,6 +1188,7 @@ out:
+ struct ceph_snapid_map* ceph_get_snapid_map(struct ceph_mds_client *mdsc,
+                                           u64 snap)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_snapid_map *sm, *exist;
+       struct rb_node **p, *parent;
+       int ret;
+@@ -1196,8 +1211,8 @@ struct ceph_snapid_map* ceph_get_snapid_
+       }
+       spin_unlock(&mdsc->snapid_map_lock);
+       if (exist) {
+-              dout("%s found snapid map %llx -> %x\n", __func__,
+-                   exist->snap, exist->dev);
++              doutc(cl, "found snapid map %llx -> %x\n", exist->snap,
++                    exist->dev);
+               return exist;
+       }
+@@ -1241,13 +1256,12 @@ struct ceph_snapid_map* ceph_get_snapid_
+       if (exist) {
+               free_anon_bdev(sm->dev);
+               kfree(sm);
+-              dout("%s found snapid map %llx -> %x\n", __func__,
+-                   exist->snap, exist->dev);
++              doutc(cl, "found snapid map %llx -> %x\n", exist->snap,
++                    exist->dev);
+               return exist;
+       }
+-      dout("%s create snapid map %llx -> %x\n", __func__,
+-           sm->snap, sm->dev);
++      doutc(cl, "create snapid map %llx -> %x\n", sm->snap, sm->dev);
+       return sm;
+ }
+@@ -1272,6 +1286,7 @@ void ceph_put_snapid_map(struct ceph_mds
+ void ceph_trim_snapid_map(struct ceph_mds_client *mdsc)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_snapid_map *sm;
+       unsigned long now;
+       LIST_HEAD(to_free);
+@@ -1293,7 +1308,7 @@ void ceph_trim_snapid_map(struct ceph_md
+       while (!list_empty(&to_free)) {
+               sm = list_first_entry(&to_free, struct ceph_snapid_map, lru);
+               list_del(&sm->lru);
+-              dout("trim snapid map %llx -> %x\n", sm->snap, sm->dev);
++              doutc(cl, "trim snapid map %llx -> %x\n", sm->snap, sm->dev);
+               free_anon_bdev(sm->dev);
+               kfree(sm);
+       }
+@@ -1301,6 +1316,7 @@ void ceph_trim_snapid_map(struct ceph_md
+ void ceph_cleanup_snapid_map(struct ceph_mds_client *mdsc)
+ {
++      struct ceph_client *cl = mdsc->fsc->client;
+       struct ceph_snapid_map *sm;
+       struct rb_node *p;
+       LIST_HEAD(to_free);
+@@ -1319,8 +1335,8 @@ void ceph_cleanup_snapid_map(struct ceph
+               list_del(&sm->lru);
+               free_anon_bdev(sm->dev);
+               if (WARN_ON_ONCE(atomic_read(&sm->ref))) {
+-                      pr_err("snapid map %llx -> %x still in use\n",
+-                             sm->snap, sm->dev);
++                      pr_err_client(cl, "snapid map %llx -> %x still in use\n",
++                                    sm->snap, sm->dev);
+               }
+               kfree(sm);
+       }
+--- a/fs/ceph/super.c
++++ b/fs/ceph/super.c
+@@ -46,9 +46,10 @@ static void ceph_put_super(struct super_
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(s);
+-      dout("put_super\n");
++      doutc(fsc->client, "begin\n");
+       ceph_fscrypt_free_dummy_policy(fsc);
+       ceph_mdsc_close_sessions(fsc->mdsc);
++      doutc(fsc->client, "done\n");
+ }
+ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
+@@ -59,13 +60,13 @@ static int ceph_statfs(struct dentry *de
+       int i, err;
+       u64 data_pool;
++      doutc(fsc->client, "begin\n");
+       if (fsc->mdsc->mdsmap->m_num_data_pg_pools == 1) {
+               data_pool = fsc->mdsc->mdsmap->m_data_pg_pools[0];
+       } else {
+               data_pool = CEPH_NOPOOL;
+       }
+-      dout("statfs\n");
+       err = ceph_monc_do_statfs(monc, data_pool, &st);
+       if (err < 0)
+               return err;
+@@ -113,24 +114,26 @@ static int ceph_statfs(struct dentry *de
+       /* fold the fs_cluster_id into the upper bits */
+       buf->f_fsid.val[1] = monc->fs_cluster_id;
++      doutc(fsc->client, "done\n");
+       return 0;
+ }
+ static int ceph_sync_fs(struct super_block *sb, int wait)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
++      struct ceph_client *cl = fsc->client;
+       if (!wait) {
+-              dout("sync_fs (non-blocking)\n");
++              doutc(cl, "(non-blocking)\n");
+               ceph_flush_dirty_caps(fsc->mdsc);
+-              dout("sync_fs (non-blocking) done\n");
++              doutc(cl, "(non-blocking) done\n");
+               return 0;
+       }
+-      dout("sync_fs (blocking)\n");
++      doutc(cl, "(blocking)\n");
+       ceph_osdc_sync(&fsc->client->osdc);
+       ceph_mdsc_sync(fsc->mdsc);
+-      dout("sync_fs (blocking) done\n");
++      doutc(cl, "(blocking) done\n");
+       return 0;
+ }
+@@ -349,7 +352,7 @@ static int ceph_parse_source(struct fs_p
+       char *dev_name = param->string, *dev_name_end;
+       int ret;
+-      dout("%s '%s'\n", __func__, dev_name);
++      dout("'%s'\n", dev_name);
+       if (!dev_name || !*dev_name)
+               return invalfc(fc, "Empty source");
+@@ -421,7 +424,7 @@ static int ceph_parse_mount_param(struct
+               return ret;
+       token = fs_parse(fc, ceph_mount_parameters, param, &result);
+-      dout("%s fs_parse '%s' token %d\n", __func__, param->key, token);
++      dout("%s: fs_parse '%s' token %d\n",__func__, param->key, token);
+       if (token < 0)
+               return token;
+@@ -891,7 +894,7 @@ static void flush_fs_workqueues(struct c
+ static void destroy_fs_client(struct ceph_fs_client *fsc)
+ {
+-      dout("destroy_fs_client %p\n", fsc);
++      doutc(fsc->client, "%p\n", fsc);
+       spin_lock(&ceph_fsc_lock);
+       list_del(&fsc->metric_wakeup);
+@@ -906,7 +909,7 @@ static void destroy_fs_client(struct cep
+       ceph_destroy_client(fsc->client);
+       kfree(fsc);
+-      dout("destroy_fs_client %p done\n", fsc);
++      dout("%s: %p done\n", __func__, fsc);
+ }
+ /*
+@@ -1028,7 +1031,7 @@ void ceph_umount_begin(struct super_bloc
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
+-      dout("ceph_umount_begin - starting forced umount\n");
++      doutc(fsc->client, "starting forced umount\n");
+       if (!fsc)
+               return;
+       fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
+@@ -1056,13 +1059,14 @@ static struct dentry *open_root_dentry(s
+                                      const char *path,
+                                      unsigned long started)
+ {
++      struct ceph_client *cl = fsc->client;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       struct ceph_mds_request *req = NULL;
+       int err;
+       struct dentry *root;
+       /* open dir */
+-      dout("open_root_inode opening '%s'\n", path);
++      doutc(cl, "opening '%s'\n", path);
+       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
+       if (IS_ERR(req))
+               return ERR_CAST(req);
+@@ -1082,13 +1086,13 @@ static struct dentry *open_root_dentry(s
+       if (err == 0) {
+               struct inode *inode = req->r_target_inode;
+               req->r_target_inode = NULL;
+-              dout("open_root_inode success\n");
++              doutc(cl, "success\n");
+               root = d_make_root(inode);
+               if (!root) {
+                       root = ERR_PTR(-ENOMEM);
+                       goto out;
+               }
+-              dout("open_root_inode success, root dentry is %p\n", root);
++              doutc(cl, "success, root dentry is %p\n", root);
+       } else {
+               root = ERR_PTR(err);
+       }
+@@ -1147,11 +1151,12 @@ static int ceph_apply_test_dummy_encrypt
+ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
+                                     struct fs_context *fc)
+ {
++      struct ceph_client *cl = fsc->client;
+       int err;
+       unsigned long started = jiffies;  /* note the start time */
+       struct dentry *root;
+-      dout("mount start %p\n", fsc);
++      doutc(cl, "mount start %p\n", fsc);
+       mutex_lock(&fsc->client->mount_mutex);
+       if (!fsc->sb->s_root) {
+@@ -1174,7 +1179,7 @@ static struct dentry *ceph_real_mount(st
+               if (err)
+                       goto out;
+-              dout("mount opening path '%s'\n", path);
++              doutc(cl, "mount opening path '%s'\n", path);
+               ceph_fs_debugfs_init(fsc);
+@@ -1189,7 +1194,7 @@ static struct dentry *ceph_real_mount(st
+       }
+       fsc->mount_state = CEPH_MOUNT_MOUNTED;
+-      dout("mount success\n");
++      doutc(cl, "mount success\n");
+       mutex_unlock(&fsc->client->mount_mutex);
+       return root;
+@@ -1202,9 +1207,10 @@ out:
+ static int ceph_set_super(struct super_block *s, struct fs_context *fc)
+ {
+       struct ceph_fs_client *fsc = s->s_fs_info;
++      struct ceph_client *cl = fsc->client;
+       int ret;
+-      dout("set_super %p\n", s);
++      doutc(cl, "%p\n", s);
+       s->s_maxbytes = MAX_LFS_FILESIZE;
+@@ -1239,30 +1245,31 @@ static int ceph_compare_super(struct sup
+       struct ceph_mount_options *fsopt = new->mount_options;
+       struct ceph_options *opt = new->client->options;
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
++      struct ceph_client *cl = fsc->client;
+-      dout("ceph_compare_super %p\n", sb);
++      doutc(cl, "%p\n", sb);
+       if (compare_mount_options(fsopt, opt, fsc)) {
+-              dout("monitor(s)/mount options don't match\n");
++              doutc(cl, "monitor(s)/mount options don't match\n");
+               return 0;
+       }
+       if ((opt->flags & CEPH_OPT_FSID) &&
+           ceph_fsid_compare(&opt->fsid, &fsc->client->fsid)) {
+-              dout("fsid doesn't match\n");
++              doutc(cl, "fsid doesn't match\n");
+               return 0;
+       }
+       if (fc->sb_flags != (sb->s_flags & ~SB_BORN)) {
+-              dout("flags differ\n");
++              doutc(cl, "flags differ\n");
+               return 0;
+       }
+       if (fsc->blocklisted && !ceph_test_mount_opt(fsc, CLEANRECOVER)) {
+-              dout("client is blocklisted (and CLEANRECOVER is not set)\n");
++              doutc(cl, "client is blocklisted (and CLEANRECOVER is not set)\n");
+               return 0;
+       }
+       if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
+-              dout("client has been forcibly unmounted\n");
++              doutc(cl, "client has been forcibly unmounted\n");
+               return 0;
+       }
+@@ -1350,8 +1357,9 @@ static int ceph_get_tree(struct fs_conte
+               err = PTR_ERR(res);
+               goto out_splat;
+       }
+-      dout("root %p inode %p ino %llx.%llx\n", res,
+-           d_inode(res), ceph_vinop(d_inode(res)));
++
++      doutc(fsc->client, "root %p inode %p ino %llx.%llx\n", res,
++                  d_inode(res), ceph_vinop(d_inode(res)));
+       fc->root = fsc->sb->s_root;
+       return 0;
+@@ -1409,7 +1417,8 @@ static int ceph_reconfigure_fc(struct fs
+               kfree(fsc->mount_options->mon_addr);
+               fsc->mount_options->mon_addr = fsopt->mon_addr;
+               fsopt->mon_addr = NULL;
+-              pr_notice("ceph: monitor addresses recorded, but not used for reconnection");
++              pr_notice_client(fsc->client,
++                      "monitor addresses recorded, but not used for reconnection");
+       }
+       sync_filesystem(sb);
+@@ -1529,10 +1538,11 @@ void ceph_dec_osd_stopping_blocker(struc
+ static void ceph_kill_sb(struct super_block *s)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(s);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       bool wait;
+-      dout("kill_sb %p\n", s);
++      doutc(cl, "%p\n", s);
+       ceph_mdsc_pre_umount(mdsc);
+       flush_fs_workqueues(fsc);
+@@ -1563,9 +1573,9 @@ static void ceph_kill_sb(struct super_bl
+                                       &mdsc->stopping_waiter,
+                                       fsc->client->options->mount_timeout);
+               if (!timeleft) /* timed out */
+-                      pr_warn("umount timed out, %ld\n", timeleft);
++                      pr_warn_client(cl, "umount timed out, %ld\n", timeleft);
+               else if (timeleft < 0) /* killed */
+-                      pr_warn("umount was killed, %ld\n", timeleft);
++                      pr_warn_client(cl, "umount was killed, %ld\n", timeleft);
+       }
+       mdsc->stopping = CEPH_MDSC_STOPPING_FLUSHED;
+--- a/fs/ceph/super.h
++++ b/fs/ceph/super.h
+@@ -506,6 +506,12 @@ ceph_sb_to_mdsc(const struct super_block
+       return (struct ceph_mds_client *)ceph_sb_to_fs_client(sb)->mdsc;
+ }
++static inline struct ceph_client *
++ceph_inode_to_client(const struct inode *inode)
++{
++      return (struct ceph_client *)ceph_inode_to_fs_client(inode)->client;
++}
++
+ static inline struct ceph_vino
+ ceph_vino(const struct inode *inode)
+ {
+--- a/fs/ceph/xattr.c
++++ b/fs/ceph/xattr.c
+@@ -58,6 +58,7 @@ static ssize_t ceph_vxattrcb_layout(stru
+                                   size_t size)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->netfs.inode.i_sb);
++      struct ceph_client *cl = fsc->client;
+       struct ceph_osd_client *osdc = &fsc->client->osdc;
+       struct ceph_string *pool_ns;
+       s64 pool = ci->i_layout.pool_id;
+@@ -69,7 +70,7 @@ static ssize_t ceph_vxattrcb_layout(stru
+       pool_ns = ceph_try_get_string(ci->i_layout.pool_ns);
+-      dout("ceph_vxattrcb_layout %p\n", &ci->netfs.inode);
++      doutc(cl, "%p\n", &ci->netfs.inode);
+       down_read(&osdc->lock);
+       pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool);
+       if (pool_name) {
+@@ -570,6 +571,8 @@ static int __set_xattr(struct ceph_inode
+                          int flags, int update_xattr,
+                          struct ceph_inode_xattr **newxattr)
+ {
++      struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct rb_node **p;
+       struct rb_node *parent = NULL;
+       struct ceph_inode_xattr *xattr = NULL;
+@@ -626,7 +629,7 @@ static int __set_xattr(struct ceph_inode
+               xattr->should_free_name = update_xattr;
+               ci->i_xattrs.count++;
+-              dout("%s count=%d\n", __func__, ci->i_xattrs.count);
++              doutc(cl, "count=%d\n", ci->i_xattrs.count);
+       } else {
+               kfree(*newxattr);
+               *newxattr = NULL;
+@@ -654,13 +657,13 @@ static int __set_xattr(struct ceph_inode
+       if (new) {
+               rb_link_node(&xattr->node, parent, p);
+               rb_insert_color(&xattr->node, &ci->i_xattrs.index);
+-              dout("%s p=%p\n", __func__, p);
++              doutc(cl, "p=%p\n", p);
+       }
+-      dout("%s added %llx.%llx xattr %p %.*s=%.*s%s\n", __func__,
+-           ceph_vinop(&ci->netfs.inode), xattr, name_len, name,
+-           min(val_len, MAX_XATTR_VAL_PRINT_LEN), val,
+-           val_len > MAX_XATTR_VAL_PRINT_LEN ? "..." : "");
++      doutc(cl, "added %p %llx.%llx xattr %p %.*s=%.*s%s\n", inode,
++            ceph_vinop(inode), xattr, name_len, name, min(val_len,
++            MAX_XATTR_VAL_PRINT_LEN), val,
++            val_len > MAX_XATTR_VAL_PRINT_LEN ? "..." : "");
+       return 0;
+ }
+@@ -668,6 +671,7 @@ static int __set_xattr(struct ceph_inode
+ static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci,
+                          const char *name)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
+       struct rb_node **p;
+       struct rb_node *parent = NULL;
+       struct ceph_inode_xattr *xattr = NULL;
+@@ -688,13 +692,13 @@ static struct ceph_inode_xattr *__get_xa
+               else {
+                       int len = min(xattr->val_len, MAX_XATTR_VAL_PRINT_LEN);
+-                      dout("%s %s: found %.*s%s\n", __func__, name, len,
+-                           xattr->val, xattr->val_len > len ? "..." : "");
++                      doutc(cl, "%s found %.*s%s\n", name, len, xattr->val,
++                            xattr->val_len > len ? "..." : "");
+                       return xattr;
+               }
+       }
+-      dout("%s %s: not found\n", __func__, name);
++      doutc(cl, "%s not found\n", name);
+       return NULL;
+ }
+@@ -735,19 +739,20 @@ static int __remove_xattr(struct ceph_in
+ static char *__copy_xattr_names(struct ceph_inode_info *ci,
+                               char *dest)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
+       struct rb_node *p;
+       struct ceph_inode_xattr *xattr = NULL;
+       p = rb_first(&ci->i_xattrs.index);
+-      dout("__copy_xattr_names count=%d\n", ci->i_xattrs.count);
++      doutc(cl, "count=%d\n", ci->i_xattrs.count);
+       while (p) {
+               xattr = rb_entry(p, struct ceph_inode_xattr, node);
+               memcpy(dest, xattr->name, xattr->name_len);
+               dest[xattr->name_len] = '\0';
+-              dout("dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name,
+-                   xattr->name_len, ci->i_xattrs.names_size);
++              doutc(cl, "dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name,
++                    xattr->name_len, ci->i_xattrs.names_size);
+               dest += xattr->name_len + 1;
+               p = rb_next(p);
+@@ -758,19 +763,19 @@ static char *__copy_xattr_names(struct c
+ void __ceph_destroy_xattrs(struct ceph_inode_info *ci)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
+       struct rb_node *p, *tmp;
+       struct ceph_inode_xattr *xattr = NULL;
+       p = rb_first(&ci->i_xattrs.index);
+-      dout("__ceph_destroy_xattrs p=%p\n", p);
++      doutc(cl, "p=%p\n", p);
+       while (p) {
+               xattr = rb_entry(p, struct ceph_inode_xattr, node);
+               tmp = p;
+               p = rb_next(tmp);
+-              dout("__ceph_destroy_xattrs next p=%p (%.*s)\n", p,
+-                   xattr->name_len, xattr->name);
++              doutc(cl, "next p=%p (%.*s)\n", p, xattr->name_len, xattr->name);
+               rb_erase(tmp, &ci->i_xattrs.index);
+               __free_xattr(xattr);
+@@ -787,6 +792,7 @@ static int __build_xattrs(struct inode *
+       __releases(ci->i_ceph_lock)
+       __acquires(ci->i_ceph_lock)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       u32 namelen;
+       u32 numattr = 0;
+       void *p, *end;
+@@ -798,8 +804,8 @@ static int __build_xattrs(struct inode *
+       int err = 0;
+       int i;
+-      dout("__build_xattrs() len=%d\n",
+-           ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0);
++      doutc(cl, "len=%d\n",
++            ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0);
+       if (ci->i_xattrs.index_version >= ci->i_xattrs.version)
+               return 0; /* already built */
+@@ -874,6 +880,8 @@ bad:
+ static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
+                                   int val_size)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
++
+       /*
+        * 4 bytes for the length, and additional 4 bytes per each xattr name,
+        * 4 bytes per each value
+@@ -881,9 +889,8 @@ static int __get_required_blob_size(stru
+       int size = 4 + ci->i_xattrs.count*(4 + 4) +
+                            ci->i_xattrs.names_size +
+                            ci->i_xattrs.vals_size;
+-      dout("__get_required_blob_size c=%d names.size=%d vals.size=%d\n",
+-           ci->i_xattrs.count, ci->i_xattrs.names_size,
+-           ci->i_xattrs.vals_size);
++      doutc(cl, "c=%d names.size=%d vals.size=%d\n", ci->i_xattrs.count,
++            ci->i_xattrs.names_size, ci->i_xattrs.vals_size);
+       if (name_size)
+               size += 4 + 4 + name_size + val_size;
+@@ -899,12 +906,14 @@ static int __get_required_blob_size(stru
+  */
+ struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci)
+ {
++      struct inode *inode = &ci->netfs.inode;
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct rb_node *p;
+       struct ceph_inode_xattr *xattr = NULL;
+       struct ceph_buffer *old_blob = NULL;
+       void *dest;
+-      dout("__build_xattrs_blob %p\n", &ci->netfs.inode);
++      doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
+       if (ci->i_xattrs.dirty) {
+               int need = __get_required_blob_size(ci, 0, 0);
+@@ -962,6 +971,7 @@ static inline int __get_request_mask(str
+ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
+                     size_t size)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_inode_xattr *xattr;
+       struct ceph_vxattr *vxattr;
+@@ -1000,8 +1010,9 @@ handle_non_vxattrs:
+       req_mask = __get_request_mask(inode);
+       spin_lock(&ci->i_ceph_lock);
+-      dout("getxattr %p name '%s' ver=%lld index_ver=%lld\n", inode, name,
+-           ci->i_xattrs.version, ci->i_xattrs.index_version);
++      doutc(cl, "%p %llx.%llx name '%s' ver=%lld index_ver=%lld\n", inode,
++            ceph_vinop(inode), name, ci->i_xattrs.version,
++            ci->i_xattrs.index_version);
+       if (ci->i_xattrs.version == 0 ||
+           !((req_mask & CEPH_CAP_XATTR_SHARED) ||
+@@ -1010,8 +1021,9 @@ handle_non_vxattrs:
+               /* security module gets xattr while filling trace */
+               if (current->journal_info) {
+-                      pr_warn_ratelimited("sync getxattr %p "
+-                                          "during filling trace\n", inode);
++                      pr_warn_ratelimited_client(cl,
++                              "sync %p %llx.%llx during filling trace\n",
++                              inode, ceph_vinop(inode));
+                       return -EBUSY;
+               }
+@@ -1053,14 +1065,16 @@ out:
+ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
+ {
+       struct inode *inode = d_inode(dentry);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       bool len_only = (size == 0);
+       u32 namelen;
+       int err;
+       spin_lock(&ci->i_ceph_lock);
+-      dout("listxattr %p ver=%lld index_ver=%lld\n", inode,
+-           ci->i_xattrs.version, ci->i_xattrs.index_version);
++      doutc(cl, "%p %llx.%llx ver=%lld index_ver=%lld\n", inode,
++            ceph_vinop(inode), ci->i_xattrs.version,
++            ci->i_xattrs.index_version);
+       if (ci->i_xattrs.version == 0 ||
+           !__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1)) {
+@@ -1095,6 +1109,7 @@ static int ceph_sync_setxattr(struct ino
+                             const char *value, size_t size, int flags)
+ {
+       struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_request *req;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+@@ -1119,7 +1134,7 @@ static int ceph_sync_setxattr(struct ino
+                       flags |= CEPH_XATTR_REMOVE;
+       }
+-      dout("setxattr value size: %zu\n", size);
++      doutc(cl, "name %s value size %zu\n", name, size);
+       /* do request */
+       req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
+@@ -1148,10 +1163,10 @@ static int ceph_sync_setxattr(struct ino
+       req->r_num_caps = 1;
+       req->r_inode_drop = CEPH_CAP_XATTR_SHARED;
+-      dout("xattr.ver (before): %lld\n", ci->i_xattrs.version);
++      doutc(cl, "xattr.ver (before): %lld\n", ci->i_xattrs.version);
+       err = ceph_mdsc_do_request(mdsc, NULL, req);
+       ceph_mdsc_put_request(req);
+-      dout("xattr.ver (after): %lld\n", ci->i_xattrs.version);
++      doutc(cl, "xattr.ver (after): %lld\n", ci->i_xattrs.version);
+ out:
+       if (pagelist)
+@@ -1162,6 +1177,7 @@ out:
+ int __ceph_setxattr(struct inode *inode, const char *name,
+                       const void *value, size_t size, int flags)
+ {
++      struct ceph_client *cl = ceph_inode_to_client(inode);
+       struct ceph_vxattr *vxattr;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
+@@ -1220,9 +1236,9 @@ retry:
+       required_blob_size = __get_required_blob_size(ci, name_len, val_len);
+       if ((ci->i_xattrs.version == 0) || !(issued & CEPH_CAP_XATTR_EXCL) ||
+           (required_blob_size > mdsc->mdsmap->m_max_xattr_size)) {
+-              dout("%s do sync setxattr: version: %llu size: %d max: %llu\n",
+-                   __func__, ci->i_xattrs.version, required_blob_size,
+-                   mdsc->mdsmap->m_max_xattr_size);
++              doutc(cl, "sync version: %llu size: %d max: %llu\n",
++                    ci->i_xattrs.version, required_blob_size,
++                    mdsc->mdsmap->m_max_xattr_size);
+               goto do_sync;
+       }
+@@ -1236,8 +1252,8 @@ retry:
+               }
+       }
+-      dout("setxattr %p name '%s' issued %s\n", inode, name,
+-           ceph_cap_string(issued));
++      doutc(cl, "%p %llx.%llx name '%s' issued %s\n", inode,
++            ceph_vinop(inode), name, ceph_cap_string(issued));
+       __build_xattrs(inode);
+       if (!ci->i_xattrs.prealloc_blob ||
+@@ -1246,7 +1262,8 @@ retry:
+               spin_unlock(&ci->i_ceph_lock);
+               ceph_buffer_put(old_blob); /* Shouldn't be required */
+-              dout(" pre-allocating new blob size=%d\n", required_blob_size);
++              doutc(cl, " pre-allocating new blob size=%d\n",
++                    required_blob_size);
+               blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
+               if (!blob)
+                       goto do_sync_unlocked;
+@@ -1286,8 +1303,9 @@ do_sync_unlocked:
+       /* security module set xattr while filling trace */
+       if (current->journal_info) {
+-              pr_warn_ratelimited("sync setxattr %p "
+-                                  "during filling trace\n", inode);
++              pr_warn_ratelimited_client(cl,
++                              "sync %p %llx.%llx during filling trace\n",
++                              inode, ceph_vinop(inode));
+               err = -EBUSY;
+       } else {
+               err = ceph_sync_setxattr(inode, name, value, size, flags);
diff --git a/queue-6.6/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch b/queue-6.6/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch
new file mode 100644 (file)
index 0000000..1f4ba07
--- /dev/null
@@ -0,0 +1,75 @@
+From stable+bounces-294163-greg=kroah.com@vger.kernel.org Fri Jul 31 19:12:12 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 12:57:01 -0400
+Subject: drm/amdgpu: Respect placement requirements in amdgpu_gtt_mgr functions
+To: stable@vger.kernel.org
+Cc: "Timur Kristóf" <timur.kristof@gmail.com>, "Christian König" <christian.koenig@amd.com>, "Alex Deucher" <alexander.deucher@amd.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260731165701.883388-1-sashal@kernel.org>
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+[ Upstream commit 8882f8897e554053af9e72f4c2da8b1e2cce56c7 ]
+
+When testing intersection and compatibility, respect
+the actual placement requirements. This is a pre-requisite
+for ensuring that UVD CS BOs do not cross 256M segments.
+
+Fixes: ded910f368a5 ("drm/amdgpu: Implement intersect/compatible functions")
+Suggested-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit bc06579ca29dee9c245a41b12e39c7bb6938af5d)
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c |   30 ++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+@@ -219,7 +219,20 @@ static bool amdgpu_gtt_mgr_intersects(st
+                                     const struct ttm_place *place,
+                                     size_t size)
+ {
+-      return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
++      const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
++      const u32 num_pages = PFN_UP(size);
++
++      if (!place->lpfn)
++              return true;
++
++      if (!amdgpu_gtt_mgr_has_gart_addr(res))
++              return false;
++
++      if (place->fpfn >= (node->start + num_pages) ||
++          (place->lpfn && place->lpfn <= node->start))
++              return false;
++
++      return true;
+ }
+ /**
+@@ -237,7 +250,20 @@ static bool amdgpu_gtt_mgr_compatible(st
+                                     const struct ttm_place *place,
+                                     size_t size)
+ {
+-      return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
++      const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
++      const u32 num_pages = PFN_UP(size);
++
++      if (!place->lpfn)
++              return true;
++
++      if (!amdgpu_gtt_mgr_has_gart_addr(res))
++              return false;
++
++      if (node->start < place->fpfn ||
++          (place->lpfn && (node->start + num_pages) > place->lpfn))
++              return false;
++
++      return true;
+ }
+ /**
diff --git a/queue-6.6/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch b/queue-6.6/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch
new file mode 100644 (file)
index 0000000..e6d6062
--- /dev/null
@@ -0,0 +1,486 @@
+From stable+bounces-294128-greg=kroah.com@vger.kernel.org Fri Jul 31 17:59:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 11:50:19 -0400
+Subject: drm/fb-helper: Allocate and release fb_info in single place
+To: stable@vger.kernel.org
+Cc: "Thomas Zimmermann" <tzimmermann@suse.de>, "Christian König" <christian.koenig@amd.com>, "Dmitry Baryshkov" <dmitry.baryshkov@oss.qualcomm.com>, "Javier Martinez Canillas" <javierm@redhat.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260731155020.604703-1-sashal@kernel.org>
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 63c971af40365ee706c7e24f6a7900d693518f09 ]
+
+Move the calls to drm_fb_helper_alloc_info() from drivers into a
+single place in fbdev helpers. Allocates struct fb_info for a new
+framebuffer device. Then call drm_fb_helper_single_fb_probe() to
+create an fbdev screen buffer. Also release the instance on errors
+by calling drm_fb_helper_release_info().
+
+Simplifies the code and fixes the error cleanup for some of the
+drivers.
+
+Regular release of the struct fb_info instance still happens in
+drm_fb_helper_fini() as before.
+
+v2:
+- remove error rollback in driver implementations (kernel test robot)
+- initialize info in TTM implementation (kernel test robot)
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Acked-by: Christian König <christian.koenig@amd.com> # radeon
+Acked-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> # msm
+Acked-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patch.msgid.link/20251027081245.80262-1-tzimmermann@suse.de
+Stable-dep-of: a18b6e30ecd6 ("drm/tegra: fbdev: Remove offset into framebuffer memory")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/armada/armada_fbdev.c      |   12 --------
+ drivers/gpu/drm/drm_fb_helper.c            |   41 +++++++++--------------------
+ drivers/gpu/drm/drm_fbdev_dma.c            |   12 --------
+ drivers/gpu/drm/drm_fbdev_generic.c        |   12 +-------
+ drivers/gpu/drm/exynos/exynos_drm_fbdev.c  |    9 ------
+ drivers/gpu/drm/gma500/fbdev.c             |   13 ---------
+ drivers/gpu/drm/i915/display/intel_fbdev.c |    9 ------
+ drivers/gpu/drm/msm/msm_fbdev.c            |    9 ------
+ drivers/gpu/drm/omapdrm/omap_fbdev.c       |    9 ------
+ drivers/gpu/drm/radeon/radeon_fbdev.c      |   13 ---------
+ drivers/gpu/drm/tegra/fbdev.c              |    9 ------
+ include/drm/drm_fb_helper.h                |   12 --------
+ 12 files changed, 25 insertions(+), 135 deletions(-)
+
+--- a/drivers/gpu/drm/armada/armada_fbdev.c
++++ b/drivers/gpu/drm/armada/armada_fbdev.c
+@@ -43,10 +43,10 @@ static int armada_fbdev_create(struct dr
+       struct drm_fb_helper_surface_size *sizes)
+ {
+       struct drm_device *dev = fbh->dev;
++      struct fb_info *info = fbh->info;
+       struct drm_mode_fb_cmd2 mode;
+       struct armada_framebuffer *dfb;
+       struct armada_gem_object *obj;
+-      struct fb_info *info;
+       int size, ret;
+       void *ptr;
+@@ -87,12 +87,6 @@ static int armada_fbdev_create(struct dr
+       if (IS_ERR(dfb))
+               return PTR_ERR(dfb);
+-      info = drm_fb_helper_alloc_info(fbh);
+-      if (IS_ERR(info)) {
+-              ret = PTR_ERR(info);
+-              goto err_fballoc;
+-      }
+-
+       info->fbops = &armada_fb_ops;
+       info->fix.smem_start = obj->phys_addr;
+       info->fix.smem_len = obj->obj.size;
+@@ -107,10 +101,6 @@ static int armada_fbdev_create(struct dr
+               (unsigned long long)obj->phys_addr);
+       return 0;
+-
+- err_fballoc:
+-      dfb->fb.funcs->destroy(&dfb->fb);
+-      return ret;
+ }
+ static int armada_fb_probe(struct drm_fb_helper *fbh,
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -499,20 +499,7 @@ int drm_fb_helper_init(struct drm_device
+ }
+ EXPORT_SYMBOL(drm_fb_helper_init);
+-/**
+- * drm_fb_helper_alloc_info - allocate fb_info and some of its members
+- * @fb_helper: driver-allocated fbdev helper
+- *
+- * A helper to alloc fb_info and the member cmap. Called by the driver
+- * within the fb_probe fb_helper callback function. Drivers do not
+- * need to release the allocated fb_info structure themselves, this is
+- * automatically done when calling drm_fb_helper_fini().
+- *
+- * RETURNS:
+- * fb_info pointer if things went okay, pointer containing error code
+- * otherwise
+- */
+-struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
++static struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
+ {
+       struct device *dev = fb_helper->dev->dev;
+       struct fb_info *info;
+@@ -538,17 +525,8 @@ err_release:
+       framebuffer_release(info);
+       return ERR_PTR(ret);
+ }
+-EXPORT_SYMBOL(drm_fb_helper_alloc_info);
+-/**
+- * drm_fb_helper_release_info - release fb_info and its members
+- * @fb_helper: driver-allocated fbdev helper
+- *
+- * A helper to release fb_info and the member cmap.  Drivers do not
+- * need to release the allocated fb_info structure themselves, this is
+- * automatically done when calling drm_fb_helper_fini().
+- */
+-void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
++static void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
+ {
+       struct fb_info *info = fb_helper->info;
+@@ -561,7 +539,6 @@ void drm_fb_helper_release_info(struct d
+               fb_dealloc_cmap(&info->cmap);
+       framebuffer_release(info);
+ }
+-EXPORT_SYMBOL(drm_fb_helper_release_info);
+ /**
+  * drm_fb_helper_unregister_info - unregister fb_info framebuffer device
+@@ -1851,6 +1828,13 @@ __drm_fb_helper_initial_config_and_unloc
+       height = dev->mode_config.max_height;
+       drm_client_modeset_probe(&fb_helper->client, width, height);
++
++      info = drm_fb_helper_alloc_info(fb_helper);
++      if (IS_ERR(info)) {
++              mutex_unlock(&fb_helper->lock);
++              return PTR_ERR(info);
++      }
++
+       ret = drm_fb_helper_single_fb_probe(fb_helper);
+       if (ret < 0) {
+               if (ret == -EAGAIN) {
+@@ -1859,13 +1843,12 @@ __drm_fb_helper_initial_config_and_unloc
+               }
+               mutex_unlock(&fb_helper->lock);
+-              return ret;
++              goto err_drm_fb_helper_release_info;
+       }
+       drm_setup_crtcs_fb(fb_helper);
+       fb_helper->deferred_setup = false;
+-      info = fb_helper->info;
+       info->var.pixclock = 0;
+       /* Need to drop locks to avoid recursive deadlock in
+@@ -1888,6 +1871,10 @@ __drm_fb_helper_initial_config_and_unloc
+       mutex_unlock(&kernel_fb_helper_lock);
+       return 0;
++
++err_drm_fb_helper_release_info:
++      drm_fb_helper_release_info(fb_helper);
++      return ret;
+ }
+ /**
+--- a/drivers/gpu/drm/drm_fbdev_dma.c
++++ b/drivers/gpu/drm/drm_fbdev_dma.c
+@@ -78,10 +78,10 @@ static int drm_fbdev_dma_helper_fb_probe
+ {
+       struct drm_client_dev *client = &fb_helper->client;
+       struct drm_device *dev = fb_helper->dev;
++      struct fb_info *info = fb_helper->info;
+       struct drm_client_buffer *buffer;
+       struct drm_gem_dma_object *dma_obj;
+       struct drm_framebuffer *fb;
+-      struct fb_info *info;
+       u32 format;
+       struct iosys_map map;
+       int ret;
+@@ -114,12 +114,6 @@ static int drm_fbdev_dma_helper_fb_probe
+       fb_helper->buffer = buffer;
+       fb_helper->fb = buffer->fb;
+-      info = drm_fb_helper_alloc_info(fb_helper);
+-      if (IS_ERR(info)) {
+-              ret = PTR_ERR(info);
+-              goto err_drm_client_buffer_vunmap;
+-      }
+-
+       drm_fb_helper_fill_info(info, fb_helper, sizes);
+       info->fbops = &drm_fbdev_dma_fb_ops;
+@@ -138,10 +132,6 @@ static int drm_fbdev_dma_helper_fb_probe
+       return 0;
+-err_drm_client_buffer_vunmap:
+-      fb_helper->fb = NULL;
+-      fb_helper->buffer = NULL;
+-      drm_client_buffer_vunmap(buffer);
+ err_drm_client_buffer_delete:
+       drm_client_framebuffer_delete(buffer);
+       return ret;
+--- a/drivers/gpu/drm/drm_fbdev_generic.c
++++ b/drivers/gpu/drm/drm_fbdev_generic.c
+@@ -73,8 +73,8 @@ static int drm_fbdev_generic_helper_fb_p
+ {
+       struct drm_client_dev *client = &fb_helper->client;
+       struct drm_device *dev = fb_helper->dev;
++      struct fb_info *info = fb_helper->info;
+       struct drm_client_buffer *buffer;
+-      struct fb_info *info;
+       size_t screen_size;
+       void *screen_buffer;
+       u32 format;
+@@ -100,12 +100,6 @@ static int drm_fbdev_generic_helper_fb_p
+               goto err_drm_client_framebuffer_delete;
+       }
+-      info = drm_fb_helper_alloc_info(fb_helper);
+-      if (IS_ERR(info)) {
+-              ret = PTR_ERR(info);
+-              goto err_vfree;
+-      }
+-
+       drm_fb_helper_fill_info(info, fb_helper, sizes);
+       info->fbops = &drm_fbdev_generic_fb_ops;
+@@ -122,12 +116,10 @@ static int drm_fbdev_generic_helper_fb_p
+       info->fbdefio = &fb_helper->fbdefio;
+       ret = fb_deferred_io_init(info);
+       if (ret)
+-              goto err_drm_fb_helper_release_info;
++              goto err_vfree;
+       return 0;
+-err_drm_fb_helper_release_info:
+-      drm_fb_helper_release_info(fb_helper);
+ err_vfree:
+       vfree(screen_buffer);
+ err_drm_client_framebuffer_delete:
+--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+@@ -60,18 +60,11 @@ static int exynos_drm_fbdev_update(struc
+                                  struct drm_fb_helper_surface_size *sizes,
+                                  struct exynos_drm_gem *exynos_gem)
+ {
+-      struct fb_info *fbi;
++      struct fb_info *fbi = helper->info;
+       struct drm_framebuffer *fb = helper->fb;
+       unsigned int size = fb->width * fb->height * fb->format->cpp[0];
+       unsigned long offset;
+-      fbi = drm_fb_helper_alloc_info(helper);
+-      if (IS_ERR(fbi)) {
+-              DRM_DEV_ERROR(to_dma_dev(helper->dev),
+-                            "failed to allocate fb info.\n");
+-              return PTR_ERR(fbi);
+-      }
+-
+       fbi->fbops = &exynos_drm_fb_ops;
+       drm_fb_helper_fill_info(fbi, helper, sizes);
+--- a/drivers/gpu/drm/gma500/fbdev.c
++++ b/drivers/gpu/drm/gma500/fbdev.c
+@@ -110,7 +110,7 @@ static int psb_fbdev_fb_probe(struct drm
+       struct drm_device *dev = fb_helper->dev;
+       struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+-      struct fb_info *info;
++      struct fb_info *info = fb_helper->info;
+       struct drm_framebuffer *fb;
+       struct drm_mode_fb_cmd2 mode_cmd = { };
+       int size;
+@@ -165,12 +165,6 @@ static int psb_fbdev_fb_probe(struct drm
+       fb_helper->fb = fb;
+-      info = drm_fb_helper_alloc_info(fb_helper);
+-      if (IS_ERR(info)) {
+-              ret = PTR_ERR(info);
+-              goto err_drm_framebuffer_unregister_private;
+-      }
+-
+       info->fbops = &psb_fbdev_fb_ops;
+       /* Accessed stolen memory directly */
+@@ -194,11 +188,6 @@ static int psb_fbdev_fb_probe(struct drm
+       return 0;
+-err_drm_framebuffer_unregister_private:
+-      drm_framebuffer_unregister_private(fb);
+-      fb->obj[0] = NULL;
+-      drm_framebuffer_cleanup(fb);
+-      kfree(fb);
+ err_drm_gem_object_put:
+       drm_gem_object_put(obj);
+       return ret;
+--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
++++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
+@@ -218,7 +218,7 @@ static int intelfb_create(struct drm_fb_
+               .type = I915_GTT_VIEW_NORMAL,
+       };
+       intel_wakeref_t wakeref;
+-      struct fb_info *info;
++      struct fb_info *info = helper->info;
+       struct i915_vma *vma;
+       unsigned long flags = 0;
+       bool prealloc = false;
+@@ -271,13 +271,6 @@ static int intelfb_create(struct drm_fb_
+               goto out_unlock;
+       }
+-      info = drm_fb_helper_alloc_info(helper);
+-      if (IS_ERR(info)) {
+-              drm_err(&dev_priv->drm, "Failed to allocate fb_info (%pe)\n", info);
+-              ret = PTR_ERR(info);
+-              goto out_unpin;
+-      }
+-
+       ifbdev->helper.fb = &ifbdev->fb->base;
+       info->fbops = &intelfb_ops;
+--- a/drivers/gpu/drm/msm/msm_fbdev.c
++++ b/drivers/gpu/drm/msm/msm_fbdev.c
+@@ -70,9 +70,9 @@ static int msm_fbdev_create(struct drm_f
+ {
+       struct drm_device *dev = helper->dev;
+       struct msm_drm_private *priv = dev->dev_private;
++      struct fb_info *fbi = helper->info;
+       struct drm_framebuffer *fb = NULL;
+       struct drm_gem_object *bo;
+-      struct fb_info *fbi = NULL;
+       uint64_t paddr;
+       uint32_t format;
+       int ret, pitch;
+@@ -105,13 +105,6 @@ static int msm_fbdev_create(struct drm_f
+               goto fail;
+       }
+-      fbi = drm_fb_helper_alloc_info(helper);
+-      if (IS_ERR(fbi)) {
+-              DRM_DEV_ERROR(dev->dev, "failed to allocate fb info\n");
+-              ret = PTR_ERR(fbi);
+-              goto fail;
+-      }
+-
+       DBG("fbi=%p, dev=%p", fbi, dev);
+       helper->fb = fb;
+--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
++++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
+@@ -131,9 +131,9 @@ static int omap_fbdev_create(struct drm_
+       struct omap_fbdev *fbdev = to_omap_fbdev(helper);
+       struct drm_device *dev = helper->dev;
+       struct omap_drm_private *priv = dev->dev_private;
++      struct fb_info *fbi = helper->info;
+       struct drm_framebuffer *fb = NULL;
+       union omap_gem_size gsize;
+-      struct fb_info *fbi = NULL;
+       struct drm_mode_fb_cmd2 mode_cmd = {0};
+       struct drm_gem_object *bo;
+       dma_addr_t dma_addr;
+@@ -199,13 +199,6 @@ static int omap_fbdev_create(struct drm_
+               goto fail;
+       }
+-      fbi = drm_fb_helper_alloc_info(helper);
+-      if (IS_ERR(fbi)) {
+-              dev_err(dev->dev, "failed to allocate fb info\n");
+-              ret = PTR_ERR(fbi);
+-              goto fail;
+-      }
+-
+       DBG("fbi=%p, dev=%p", fbi, dev);
+       helper->fb = fb;
+--- a/drivers/gpu/drm/radeon/radeon_fbdev.c
++++ b/drivers/gpu/drm/radeon/radeon_fbdev.c
+@@ -207,7 +207,7 @@ static int radeon_fbdev_fb_helper_fb_pro
+ {
+       struct radeon_device *rdev = fb_helper->dev->dev_private;
+       struct drm_mode_fb_cmd2 mode_cmd = { };
+-      struct fb_info *info;
++      struct fb_info *info = fb_helper->info;
+       struct drm_gem_object *gobj;
+       struct radeon_bo *rbo;
+       struct drm_framebuffer *fb;
+@@ -245,13 +245,6 @@ static int radeon_fbdev_fb_helper_fb_pro
+       /* setup helper */
+       fb_helper->fb = fb;
+-      /* okay we have an object now allocate the framebuffer */
+-      info = drm_fb_helper_alloc_info(fb_helper);
+-      if (IS_ERR(info)) {
+-              ret = PTR_ERR(info);
+-              goto err_drm_framebuffer_unregister_private;
+-      }
+-
+       info->fbops = &radeon_fbdev_fb_ops;
+       /* radeon resume is fragile and needs a vt switch to help it along */
+@@ -277,10 +270,6 @@ static int radeon_fbdev_fb_helper_fb_pro
+       return 0;
+-err_drm_framebuffer_unregister_private:
+-      fb_helper->fb = NULL;
+-      drm_framebuffer_unregister_private(fb);
+-      drm_framebuffer_cleanup(fb);
+ err_kfree:
+       kfree(fb);
+ err_radeon_fbdev_destroy_pinned_object:
+--- a/drivers/gpu/drm/tegra/fbdev.c
++++ b/drivers/gpu/drm/tegra/fbdev.c
+@@ -72,10 +72,10 @@ static int tegra_fbdev_probe(struct drm_
+       struct tegra_drm *tegra = helper->dev->dev_private;
+       struct drm_device *drm = helper->dev;
+       struct drm_mode_fb_cmd2 cmd = { 0 };
++      struct fb_info *info = helper->info;
+       unsigned int bytes_per_pixel;
+       struct drm_framebuffer *fb;
+       unsigned long offset;
+-      struct fb_info *info;
+       struct tegra_bo *bo;
+       size_t size;
+       int err;
+@@ -96,13 +96,6 @@ static int tegra_fbdev_probe(struct drm_
+       if (IS_ERR(bo))
+               return PTR_ERR(bo);
+-      info = drm_fb_helper_alloc_info(helper);
+-      if (IS_ERR(info)) {
+-              dev_err(drm->dev, "failed to allocate framebuffer info\n");
+-              drm_gem_object_put(&bo->gem);
+-              return PTR_ERR(info);
+-      }
+-
+       fb = tegra_fb_alloc(drm, &cmd, &bo, 1);
+       if (IS_ERR(fb)) {
+               err = PTR_ERR(fb);
+--- a/include/drm/drm_fb_helper.h
++++ b/include/drm/drm_fb_helper.h
+@@ -246,8 +246,6 @@ int drm_fb_helper_check_var(struct fb_va
+ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
+-struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper);
+-void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper);
+ void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper);
+ void drm_fb_helper_fill_info(struct fb_info *info,
+                            struct drm_fb_helper *fb_helper,
+@@ -330,16 +328,6 @@ drm_fb_helper_restore_fbdev_mode_unlocke
+       return 0;
+ }
+-static inline struct fb_info *
+-drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
+-{
+-      return NULL;
+-}
+-
+-static inline void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
+-{
+-}
+-
+ static inline void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper)
+ {
+ }
diff --git a/queue-6.6/drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch b/queue-6.6/drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch
new file mode 100644 (file)
index 0000000..9912721
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-294471-greg=kroah.com@vger.kernel.org Sun Aug  2 05:43:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat,  1 Aug 2026 23:42:44 -0400
+Subject: drm/i915/vrr: Check HAS_VRR() first in intel_vrr_is_capable()
+To: stable@vger.kernel.org
+Cc: "Ville Syrjälä" <ville.syrjala@linux.intel.com>, "Ankit Nautiyal" <ankit.k.nautiyal@intel.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260802034245.2976489-1-sashal@kernel.org>
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+[ Upstream commit 4b274b0b61ab2a529e5c22e9aa033f3028e639fc ]
+
+There's no point in doing all the other checks in
+intel_vrr_is_capable() if the platform doesn't support VRR at all
+Check HAS_VRR() before wasting time on the other checks.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20251020185038.4272-23-ville.syrjala@linux.intel.com
+Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
+Stable-dep-of: f8a9262c7a6f ("drm/i915/vrr: require valid min/max vfreq for VRR")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_vrr.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_vrr.c
++++ b/drivers/gpu/drm/i915/display/intel_vrr.c
+@@ -16,6 +16,9 @@ bool intel_vrr_is_capable(struct intel_c
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+       struct intel_dp *intel_dp;
++      if (!HAS_VRR(i915))
++              return false;
++
+       /*
+        * DP Sink is capable of VRR video timings if
+        * Ignore MSA bit is set in DPCD.
+@@ -38,8 +41,7 @@ bool intel_vrr_is_capable(struct intel_c
+               return false;
+       }
+-      return HAS_VRR(i915) &&
+-              info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
++      return info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
+ }
+ void
diff --git a/queue-6.6/drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch b/queue-6.6/drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch
new file mode 100644 (file)
index 0000000..fa59b8c
--- /dev/null
@@ -0,0 +1,49 @@
+From stable+bounces-294472-greg=kroah.com@vger.kernel.org Sun Aug  2 05:44:02 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat,  1 Aug 2026 23:42:45 -0400
+Subject: drm/i915/vrr: require valid min/max vfreq for VRR
+To: stable@vger.kernel.org
+Cc: Jani Nikula <jani.nikula@intel.com>, Martin Hodo <martin.hodo@intel.com>, Ankit Nautiyal <ankit.k.nautiyal@intel.com>, Joonas Lahtinen <joonas.lahtinen@linux.intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260802034245.2976489-2-sashal@kernel.org>
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+[ Upstream commit f8a9262c7a6fc2de9802e14b0228114f0333869e ]
+
+Ensure the EDID provided min/max vfreq are valid. Most scenarios are
+already covered (by coincidence) through the checks in
+intel_vrr_is_capable() and intel_vrr_is_in_range(), but be more explicit
+about it. At worst, a zero min_vfreq could lead to a division by zero in
+intel_vrr_compute_vmax().
+
+Discovered using AI-assisted static analysis confirmed by Intel Product
+Security.
+
+Reported-by: Martin Hodo <martin.hodo@intel.com>
+Fixes: 117cd09ba528 ("drm/i915/display/dp: Compute VRR state in atomic_check")
+Cc: stable@vger.kernel.org # v5.12+
+Cc: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
+Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
+Link: https://patch.msgid.link/20260625131040.1051272-1-jani.nikula@intel.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 1765cf59f517b02f3b0591fe5120930d08bddeb6)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_vrr.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/i915/display/intel_vrr.c
++++ b/drivers/gpu/drm/i915/display/intel_vrr.c
+@@ -41,6 +41,10 @@ bool intel_vrr_is_capable(struct intel_c
+               return false;
+       }
++      if (!info->monitor_range.min_vfreq || !info->monitor_range.max_vfreq ||
++          info->monitor_range.min_vfreq > info->monitor_range.max_vfreq)
++              return false;
++
+       return info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
+ }
diff --git a/queue-6.6/drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch b/queue-6.6/drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch
new file mode 100644 (file)
index 0000000..bceb566
--- /dev/null
@@ -0,0 +1,2054 @@
+From stable+bounces-293837-greg=kroah.com@vger.kernel.org Thu Jul 30 21:39:22 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 15:29:54 -0400
+Subject: drm: renesas: Move RZ/G2L MIPI DSI driver to rz-du
+To: stable@vger.kernel.org
+Cc: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>, Biju Das <biju.das.jz@bp.renesas.com>, Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260730192955.3124753-1-sashal@kernel.org>
+
+From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+[ Upstream commit 1b5dfd1881dbe303536d4167500b94549ff2f6a7 ]
+
+All the RZ/G2L DU specific components are located under the rz-du folder,
+so it makes sense to move the RZ/G2L MIPI DSI driver there instead of
+keeping it in the rcar-du folder. This change improves the organization
+and modularity of the driver configuration by grouping related settings together.
+
+Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Acked-by: Biju Das <biju.das.jz@bp.renesas.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240625123244.200533-1-prabhakar.mahadev-lad.rj@bp.renesas.com
+Stable-dep-of: 7cbba8a8ba02 ("drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/renesas/Kconfig                           | 1 +
+ drivers/gpu/drm/renesas/Makefile                          | 1 +
+ drivers/gpu/drm/renesas/rcar-du/Kconfig                   | 8 --------
+ drivers/gpu/drm/renesas/rcar-du/Makefile                  | 2 --
+ drivers/gpu/drm/renesas/rz-du/Kconfig                     | 8 ++++++++
+ drivers/gpu/drm/renesas/rz-du/Makefile                    | 3 +++
+ .../gpu/drm/renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi.c   | 0
+ .../drm/renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi_regs.h  | 0
+ drivers/gpu/drm/renesas/Kconfig                       |    1 
+ drivers/gpu/drm/renesas/Makefile                      |    1 
+ drivers/gpu/drm/renesas/rcar-du/Kconfig               |    8 
+ drivers/gpu/drm/renesas/rcar-du/Makefile              |    2 
+ drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c      |  816 ------------------
+ drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h |  151 ---
+ drivers/gpu/drm/renesas/rz-du/Kconfig                 |    8 
+ drivers/gpu/drm/renesas/rz-du/Makefile                |    3 
+ drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c        |  816 ++++++++++++++++++
+ drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  151 +++
+ 10 files changed, 980 insertions(+), 977 deletions(-)
+ create mode 100644 drivers/gpu/drm/renesas/rz-du/Kconfig
+ create mode 100644 drivers/gpu/drm/renesas/rz-du/Makefile
+ rename drivers/gpu/drm/renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi.c (100%)
+ rename drivers/gpu/drm/renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi_regs.h (100%)
+
+--- a/drivers/gpu/drm/renesas/Kconfig
++++ b/drivers/gpu/drm/renesas/Kconfig
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ source "drivers/gpu/drm/renesas/rcar-du/Kconfig"
++source "drivers/gpu/drm/renesas/rz-du/Kconfig"
+ source "drivers/gpu/drm/renesas/shmobile/Kconfig"
+--- a/drivers/gpu/drm/renesas/Makefile
++++ b/drivers/gpu/drm/renesas/Makefile
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-y += rcar-du/
++obj-y += rz-du/
+ obj-$(CONFIG_DRM_SHMOBILE) += shmobile/
+--- a/drivers/gpu/drm/renesas/rcar-du/Kconfig
++++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig
+@@ -60,14 +60,6 @@ config DRM_RCAR_MIPI_DSI
+       select DRM_MIPI_DSI
+       select RESET_CONTROLLER
+-config DRM_RZG2L_MIPI_DSI
+-      tristate "RZ/G2L MIPI DSI Encoder Support"
+-      depends on DRM && DRM_BRIDGE && OF
+-      depends on ARCH_RENESAS || COMPILE_TEST
+-      select DRM_MIPI_DSI
+-      help
+-        Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders.
+-
+ config DRM_RCAR_VSP
+       bool "R-Car DU VSP Compositor Support" if ARM
+       default y if ARM64
+--- a/drivers/gpu/drm/renesas/rcar-du/Makefile
++++ b/drivers/gpu/drm/renesas/rcar-du/Makefile
+@@ -14,5 +14,3 @@ obj-$(CONFIG_DRM_RCAR_DU)            += rcar-du-dr
+ obj-$(CONFIG_DRM_RCAR_DW_HDMI)                += rcar_dw_hdmi.o
+ obj-$(CONFIG_DRM_RCAR_LVDS)           += rcar_lvds.o
+ obj-$(CONFIG_DRM_RCAR_MIPI_DSI)               += rcar_mipi_dsi.o
+-
+-obj-$(CONFIG_DRM_RZG2L_MIPI_DSI)      += rzg2l_mipi_dsi.o
+--- a/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c
++++ /dev/null
+@@ -1,816 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * RZ/G2L MIPI DSI Encoder Driver
+- *
+- * Copyright (C) 2022 Renesas Electronics Corporation
+- */
+-#include <linux/clk.h>
+-#include <linux/delay.h>
+-#include <linux/io.h>
+-#include <linux/iopoll.h>
+-#include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/of_graph.h>
+-#include <linux/platform_device.h>
+-#include <linux/pm_runtime.h>
+-#include <linux/reset.h>
+-#include <linux/slab.h>
+-
+-#include <drm/drm_atomic.h>
+-#include <drm/drm_atomic_helper.h>
+-#include <drm/drm_bridge.h>
+-#include <drm/drm_mipi_dsi.h>
+-#include <drm/drm_of.h>
+-#include <drm/drm_panel.h>
+-#include <drm/drm_probe_helper.h>
+-
+-#include "rzg2l_mipi_dsi_regs.h"
+-
+-struct rzg2l_mipi_dsi {
+-      struct device *dev;
+-      void __iomem *mmio;
+-
+-      struct reset_control *rstc;
+-      struct reset_control *arstc;
+-      struct reset_control *prstc;
+-
+-      struct mipi_dsi_host host;
+-      struct drm_bridge bridge;
+-      struct drm_bridge *next_bridge;
+-
+-      struct clk *vclk;
+-
+-      enum mipi_dsi_pixel_format format;
+-      unsigned int num_data_lanes;
+-      unsigned int lanes;
+-      unsigned long mode_flags;
+-};
+-
+-static inline struct rzg2l_mipi_dsi *
+-bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge)
+-{
+-      return container_of(bridge, struct rzg2l_mipi_dsi, bridge);
+-}
+-
+-static inline struct rzg2l_mipi_dsi *
+-host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host)
+-{
+-      return container_of(host, struct rzg2l_mipi_dsi, host);
+-}
+-
+-struct rzg2l_mipi_dsi_timings {
+-      unsigned long hsfreq_max;
+-      u32 t_init;
+-      u32 tclk_prepare;
+-      u32 ths_prepare;
+-      u32 tclk_zero;
+-      u32 tclk_pre;
+-      u32 tclk_post;
+-      u32 tclk_trail;
+-      u32 ths_zero;
+-      u32 ths_trail;
+-      u32 ths_exit;
+-      u32 tlpx;
+-};
+-
+-static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {
+-      {
+-              .hsfreq_max = 80000,
+-              .t_init = 79801,
+-              .tclk_prepare = 8,
+-              .ths_prepare = 13,
+-              .tclk_zero = 33,
+-              .tclk_pre = 24,
+-              .tclk_post = 94,
+-              .tclk_trail = 10,
+-              .ths_zero = 23,
+-              .ths_trail = 17,
+-              .ths_exit = 13,
+-              .tlpx = 6,
+-      },
+-      {
+-              .hsfreq_max = 125000,
+-              .t_init = 79801,
+-              .tclk_prepare = 8,
+-              .ths_prepare = 12,
+-              .tclk_zero = 33,
+-              .tclk_pre = 15,
+-              .tclk_post = 94,
+-              .tclk_trail = 10,
+-              .ths_zero = 23,
+-              .ths_trail = 17,
+-              .ths_exit = 13,
+-              .tlpx = 6,
+-      },
+-      {
+-              .hsfreq_max = 250000,
+-              .t_init = 79801,
+-              .tclk_prepare = 8,
+-              .ths_prepare = 12,
+-              .tclk_zero = 33,
+-              .tclk_pre = 13,
+-              .tclk_post = 94,
+-              .tclk_trail = 10,
+-              .ths_zero = 23,
+-              .ths_trail = 16,
+-              .ths_exit = 13,
+-              .tlpx = 6,
+-      },
+-      {
+-              .hsfreq_max = 360000,
+-              .t_init = 79801,
+-              .tclk_prepare = 8,
+-              .ths_prepare = 10,
+-              .tclk_zero = 33,
+-              .tclk_pre = 4,
+-              .tclk_post = 35,
+-              .tclk_trail = 7,
+-              .ths_zero = 16,
+-              .ths_trail = 9,
+-              .ths_exit = 13,
+-              .tlpx = 6,
+-      },
+-      {
+-              .hsfreq_max = 720000,
+-              .t_init = 79801,
+-              .tclk_prepare = 8,
+-              .ths_prepare = 9,
+-              .tclk_zero = 33,
+-              .tclk_pre = 4,
+-              .tclk_post = 35,
+-              .tclk_trail = 7,
+-              .ths_zero = 16,
+-              .ths_trail = 9,
+-              .ths_exit = 13,
+-              .tlpx = 6,
+-      },
+-      {
+-              .hsfreq_max = 1500000,
+-              .t_init = 79801,
+-              .tclk_prepare = 8,
+-              .ths_prepare = 9,
+-              .tclk_zero = 33,
+-              .tclk_pre = 4,
+-              .tclk_post = 35,
+-              .tclk_trail = 7,
+-              .ths_zero = 16,
+-              .ths_trail = 9,
+-              .ths_exit = 13,
+-              .tlpx = 6,
+-      },
+-};
+-
+-static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
+-{
+-      iowrite32(data, dsi->mmio + reg);
+-}
+-
+-static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
+-{
+-      iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);
+-}
+-
+-static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
+-{
+-      return ioread32(dsi->mmio + reg);
+-}
+-
+-static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
+-{
+-      return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);
+-}
+-
+-/* -----------------------------------------------------------------------------
+- * Hardware Setup
+- */
+-
+-static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
+-                                  unsigned long hsfreq)
+-{
+-      const struct rzg2l_mipi_dsi_timings *dphy_timings;
+-      unsigned int i;
+-      u32 dphyctrl0;
+-      u32 dphytim0;
+-      u32 dphytim1;
+-      u32 dphytim2;
+-      u32 dphytim3;
+-      int ret;
+-
+-      /* All DSI global operation timings are set with recommended setting */
+-      for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) {
+-              dphy_timings = &rzg2l_mipi_dsi_global_timings[i];
+-              if (hsfreq <= dphy_timings->hsfreq_max)
+-                      break;
+-      }
+-
+-      /* Initializing DPHY before accessing LINK */
+-      dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN |
+-                  DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR;
+-
+-      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+-      usleep_range(20, 30);
+-
+-      dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200;
+-      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+-      usleep_range(10, 20);
+-
+-      dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) |
+-                 DSIDPHYTIM0_T_INIT(dphy_timings->t_init);
+-      dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) |
+-                 DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) |
+-                 DSIDPHYTIM1_THS_SETTLE(0) |
+-                 DSIDPHYTIM1_TCLK_SETTLE(0);
+-      dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) |
+-                 DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) |
+-                 DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) |
+-                 DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero);
+-      dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) |
+-                 DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) |
+-                 DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) |
+-                 DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero);
+-
+-      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0);
+-      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1);
+-      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2);
+-      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3);
+-
+-      ret = reset_control_deassert(dsi->rstc);
+-      if (ret < 0)
+-              return ret;
+-
+-      udelay(1);
+-
+-      return 0;
+-}
+-
+-static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)
+-{
+-      u32 dphyctrl0;
+-
+-      dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0);
+-
+-      dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR);
+-      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+-
+-      reset_control_assert(dsi->rstc);
+-}
+-
+-static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
+-                                const struct drm_display_mode *mode)
+-{
+-      unsigned long hsfreq;
+-      unsigned int bpp;
+-      u32 txsetr;
+-      u32 clstptsetr;
+-      u32 lptrnstsetr;
+-      u32 clkkpt;
+-      u32 clkbfht;
+-      u32 clkstpt;
+-      u32 golpbkt;
+-      int ret;
+-
+-      /*
+-       * Relationship between hsclk and vclk must follow
+-       * vclk * bpp = hsclk * 8 * lanes
+-       * where vclk: video clock (Hz)
+-       *       bpp: video pixel bit depth
+-       *       hsclk: DSI HS Byte clock frequency (Hz)
+-       *       lanes: number of data lanes
+-       *
+-       * hsclk(bit) = hsclk(byte) * 8
+-       */
+-      bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+-      hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);
+-
+-      ret = pm_runtime_resume_and_get(dsi->dev);
+-      if (ret < 0)
+-              return ret;
+-
+-      clk_set_rate(dsi->vclk, mode->clock * 1000);
+-
+-      ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
+-      if (ret < 0)
+-              goto err_phy;
+-
+-      /* Enable Data lanes and Clock lanes */
+-      txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN;
+-      rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);
+-
+-      /*
+-       * Global timings characteristic depends on high speed Clock Frequency
+-       * Currently MIPI DSI-IF just supports maximum FHD@60 with:
+-       * - videoclock = 148.5 (MHz)
+-       * - bpp: maximum 24bpp
+-       * - data lanes: maximum 4 lanes
+-       * Therefore maximum hsclk will be 891 Mbps.
+-       */
+-      if (hsfreq > 445500) {
+-              clkkpt = 12;
+-              clkbfht = 15;
+-              clkstpt = 48;
+-              golpbkt = 75;
+-      } else if (hsfreq > 250000) {
+-              clkkpt = 7;
+-              clkbfht = 8;
+-              clkstpt = 27;
+-              golpbkt = 40;
+-      } else {
+-              clkkpt = 8;
+-              clkbfht = 6;
+-              clkstpt = 24;
+-              golpbkt = 29;
+-      }
+-
+-      clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) |
+-                   CLSTPTSETR_CLKSTPT(clkstpt);
+-      rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr);
+-
+-      lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
+-      rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
+-
+-      return 0;
+-
+-err_phy:
+-      rzg2l_mipi_dsi_dphy_exit(dsi);
+-      pm_runtime_put(dsi->dev);
+-
+-      return ret;
+-}
+-
+-static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)
+-{
+-      rzg2l_mipi_dsi_dphy_exit(dsi);
+-      pm_runtime_put(dsi->dev);
+-}
+-
+-static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,
+-                                            const struct drm_display_mode *mode)
+-{
+-      u32 vich1ppsetr;
+-      u32 vich1vssetr;
+-      u32 vich1vpsetr;
+-      u32 vich1hssetr;
+-      u32 vich1hpsetr;
+-      int dsi_format;
+-      u32 delay[2];
+-      u8 index;
+-
+-      /* Configuration for Pixel Packet */
+-      dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format);
+-      switch (dsi_format) {
+-      case 24:
+-              vich1ppsetr = VICH1PPSETR_DT_RGB24;
+-              break;
+-      case 18:
+-              vich1ppsetr = VICH1PPSETR_DT_RGB18;
+-              break;
+-      }
+-
+-      if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) &&
+-          !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))
+-              vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE;
+-
+-      rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr);
+-
+-      /* Configuration for Video Parameters */
+-      vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) |
+-                    VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start);
+-      vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ?
+-                      VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW;
+-
+-      vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) |
+-                    VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end);
+-
+-      vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) |
+-                    VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start);
+-      vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ?
+-                      VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW;
+-
+-      vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) |
+-                    VICH1HPSETR_HBP(mode->htotal - mode->hsync_end);
+-
+-      rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr);
+-      rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr);
+-      rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr);
+-      rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr);
+-
+-      /*
+-       * Configuration for Delay Value
+-       * Delay value based on 2 ranges of video clock.
+-       * 74.25MHz is videoclock of HD@60p or FHD@30p
+-       */
+-      if (mode->clock > 74250) {
+-              delay[0] = 231;
+-              delay[1] = 216;
+-      } else {
+-              delay[0] = 220;
+-              delay[1] = 212;
+-      }
+-
+-      if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+-              index = 0;
+-      else
+-              index = 1;
+-
+-      rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R,
+-                                VICH1SET1R_DLY(delay[index]));
+-}
+-
+-static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi)
+-{
+-      bool is_clk_cont;
+-      u32 hsclksetr;
+-      u32 status;
+-      int ret;
+-
+-      is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
+-
+-      /* Start HS clock */
+-      hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ?
+-                                           HSCLKSETR_HSCLKMODE_CONT :
+-                                           HSCLKSETR_HSCLKMODE_NON_CONT);
+-      rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr);
+-
+-      if (is_clk_cont) {
+-              ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+-                                      status & PLSR_CLLP2HS,
+-                                      2000, 20000, false, dsi, PLSR);
+-              if (ret < 0) {
+-                      dev_err(dsi->dev, "failed to start HS clock\n");
+-                      return ret;
+-              }
+-      }
+-
+-      dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode",
+-              is_clk_cont ? "continuous" : "non-continuous");
+-
+-      return 0;
+-}
+-
+-static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi)
+-{
+-      bool is_clk_cont;
+-      u32 status;
+-      int ret;
+-
+-      is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
+-
+-      /* Stop HS clock */
+-      rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR,
+-                                is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT :
+-                                HSCLKSETR_HSCLKMODE_NON_CONT);
+-
+-      if (is_clk_cont) {
+-              ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+-                                      status & PLSR_CLHS2LP,
+-                                      2000, 20000, false, dsi, PLSR);
+-              if (ret < 0) {
+-                      dev_err(dsi->dev, "failed to stop HS clock\n");
+-                      return ret;
+-              }
+-      }
+-
+-      return 0;
+-}
+-
+-static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi)
+-{
+-      u32 vich1set0r;
+-      u32 status;
+-      int ret;
+-
+-      /* Configuration for Blanking sequence and start video input*/
+-      vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP |
+-                   VICH1SET0R_HSANOLP | VICH1SET0R_VSTART;
+-      rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r);
+-
+-      ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+-                              status & VICH1SR_VIRDY,
+-                              2000, 20000, false, dsi, VICH1SR);
+-      if (ret < 0)
+-              dev_err(dsi->dev, "Failed to start video signal input\n");
+-
+-      return ret;
+-}
+-
+-static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi)
+-{
+-      u32 status;
+-      int ret;
+-
+-      rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT);
+-      ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+-                              (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)),
+-                              2000, 20000, false, dsi, VICH1SR);
+-      if (ret < 0)
+-              goto err;
+-
+-      ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+-                              !(status & LINKSR_HSBUSY),
+-                              2000, 20000, false, dsi, LINKSR);
+-      if (ret < 0)
+-              goto err;
+-
+-      return 0;
+-
+-err:
+-      dev_err(dsi->dev, "Failed to stop video signal input\n");
+-      return ret;
+-}
+-
+-/* -----------------------------------------------------------------------------
+- * Bridge
+- */
+-
+-static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,
+-                               enum drm_bridge_attach_flags flags)
+-{
+-      struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+-
+-      return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge,
+-                               flags);
+-}
+-
+-static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
+-                                       struct drm_bridge_state *old_bridge_state)
+-{
+-      struct drm_atomic_state *state = old_bridge_state->base.state;
+-      struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+-      const struct drm_display_mode *mode;
+-      struct drm_connector *connector;
+-      struct drm_crtc *crtc;
+-      int ret;
+-
+-      connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+-      crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+-      mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
+-
+-      ret = rzg2l_mipi_dsi_startup(dsi, mode);
+-      if (ret < 0)
+-              return;
+-
+-      rzg2l_mipi_dsi_set_display_timing(dsi, mode);
+-
+-      ret = rzg2l_mipi_dsi_start_hs_clock(dsi);
+-      if (ret < 0)
+-              goto err_stop;
+-
+-      ret = rzg2l_mipi_dsi_start_video(dsi);
+-      if (ret < 0)
+-              goto err_stop_clock;
+-
+-      return;
+-
+-err_stop_clock:
+-      rzg2l_mipi_dsi_stop_hs_clock(dsi);
+-err_stop:
+-      rzg2l_mipi_dsi_stop(dsi);
+-}
+-
+-static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,
+-                                        struct drm_bridge_state *old_bridge_state)
+-{
+-      struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+-
+-      rzg2l_mipi_dsi_stop_video(dsi);
+-      rzg2l_mipi_dsi_stop_hs_clock(dsi);
+-      rzg2l_mipi_dsi_stop(dsi);
+-}
+-
+-static enum drm_mode_status
+-rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
+-                               const struct drm_display_info *info,
+-                               const struct drm_display_mode *mode)
+-{
+-      if (mode->clock > 148500)
+-              return MODE_CLOCK_HIGH;
+-
+-      if (mode->clock < 5803)
+-              return MODE_CLOCK_LOW;
+-
+-      return MODE_OK;
+-}
+-
+-static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {
+-      .attach = rzg2l_mipi_dsi_attach,
+-      .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+-      .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+-      .atomic_reset = drm_atomic_helper_bridge_reset,
+-      .atomic_enable = rzg2l_mipi_dsi_atomic_enable,
+-      .atomic_disable = rzg2l_mipi_dsi_atomic_disable,
+-      .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,
+-};
+-
+-/* -----------------------------------------------------------------------------
+- * Host setting
+- */
+-
+-static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
+-                                    struct mipi_dsi_device *device)
+-{
+-      struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+-      int ret;
+-
+-      if (device->lanes > dsi->num_data_lanes) {
+-              dev_err(dsi->dev,
+-                      "Number of lines of device (%u) exceeds host (%u)\n",
+-                      device->lanes, dsi->num_data_lanes);
+-              return -EINVAL;
+-      }
+-
+-      switch (mipi_dsi_pixel_format_to_bpp(device->format)) {
+-      case 24:
+-      case 18:
+-              break;
+-      default:
+-              dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format);
+-              return -EINVAL;
+-      }
+-
+-      dsi->lanes = device->lanes;
+-      dsi->format = device->format;
+-      dsi->mode_flags = device->mode_flags;
+-
+-      dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node,
+-                                                1, 0);
+-      if (IS_ERR(dsi->next_bridge)) {
+-              ret = PTR_ERR(dsi->next_bridge);
+-              dev_err(dsi->dev, "failed to get next bridge: %d\n", ret);
+-              return ret;
+-      }
+-
+-      drm_bridge_add(&dsi->bridge);
+-
+-      return 0;
+-}
+-
+-static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
+-                                    struct mipi_dsi_device *device)
+-{
+-      struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+-
+-      drm_bridge_remove(&dsi->bridge);
+-
+-      return 0;
+-}
+-
+-static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
+-      .attach = rzg2l_mipi_dsi_host_attach,
+-      .detach = rzg2l_mipi_dsi_host_detach,
+-};
+-
+-/* -----------------------------------------------------------------------------
+- * Power Management
+- */
+-
+-static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev)
+-{
+-      struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
+-
+-      reset_control_assert(dsi->prstc);
+-      reset_control_assert(dsi->arstc);
+-
+-      return 0;
+-}
+-
+-static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev)
+-{
+-      struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
+-      int ret;
+-
+-      ret = reset_control_deassert(dsi->arstc);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = reset_control_deassert(dsi->prstc);
+-      if (ret < 0)
+-              reset_control_assert(dsi->arstc);
+-
+-      return ret;
+-}
+-
+-static const struct dev_pm_ops rzg2l_mipi_pm_ops = {
+-      SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL)
+-};
+-
+-/* -----------------------------------------------------------------------------
+- * Probe & Remove
+- */
+-
+-static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
+-{
+-      unsigned int num_data_lanes;
+-      struct rzg2l_mipi_dsi *dsi;
+-      u32 txsetr;
+-      int ret;
+-
+-      dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
+-      if (!dsi)
+-              return -ENOMEM;
+-
+-      platform_set_drvdata(pdev, dsi);
+-      dsi->dev = &pdev->dev;
+-
+-      ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4);
+-      if (ret < 0)
+-              return dev_err_probe(dsi->dev, ret,
+-                                   "missing or invalid data-lanes property\n");
+-
+-      num_data_lanes = ret;
+-
+-      dsi->mmio = devm_platform_ioremap_resource(pdev, 0);
+-      if (IS_ERR(dsi->mmio))
+-              return PTR_ERR(dsi->mmio);
+-
+-      dsi->vclk = devm_clk_get(dsi->dev, "vclk");
+-      if (IS_ERR(dsi->vclk))
+-              return PTR_ERR(dsi->vclk);
+-
+-      dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst");
+-      if (IS_ERR(dsi->rstc))
+-              return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc),
+-                                   "failed to get rst\n");
+-
+-      dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst");
+-      if (IS_ERR(dsi->arstc))
+-              return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc),
+-                                   "failed to get arst\n");
+-
+-      dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst");
+-      if (IS_ERR(dsi->prstc))
+-              return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc),
+-                                   "failed to get prst\n");
+-
+-      platform_set_drvdata(pdev, dsi);
+-
+-      pm_runtime_enable(dsi->dev);
+-
+-      ret = pm_runtime_resume_and_get(dsi->dev);
+-      if (ret < 0)
+-              goto err_pm_disable;
+-
+-      /*
+-       * TXSETR register can be read only after DPHY init. But during probe
+-       * mode->clock and format are not available. So initialize DPHY with
+-       * timing parameters for 80Mbps.
+-       */
+-      ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000);
+-      if (ret < 0)
+-              goto err_phy;
+-
+-      txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);
+-      dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);
+-      rzg2l_mipi_dsi_dphy_exit(dsi);
+-      pm_runtime_put(dsi->dev);
+-
+-      /* Initialize the DRM bridge. */
+-      dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops;
+-      dsi->bridge.of_node = dsi->dev->of_node;
+-
+-      /* Init host device */
+-      dsi->host.dev = dsi->dev;
+-      dsi->host.ops = &rzg2l_mipi_dsi_host_ops;
+-      ret = mipi_dsi_host_register(&dsi->host);
+-      if (ret < 0)
+-              goto err_pm_disable;
+-
+-      return 0;
+-
+-err_phy:
+-      rzg2l_mipi_dsi_dphy_exit(dsi);
+-      pm_runtime_put(dsi->dev);
+-err_pm_disable:
+-      pm_runtime_disable(dsi->dev);
+-      return ret;
+-}
+-
+-static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)
+-{
+-      struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);
+-
+-      mipi_dsi_host_unregister(&dsi->host);
+-      pm_runtime_disable(&pdev->dev);
+-}
+-
+-static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {
+-      { .compatible = "renesas,rzg2l-mipi-dsi" },
+-      { /* sentinel */ }
+-};
+-
+-MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table);
+-
+-static struct platform_driver rzg2l_mipi_dsi_platform_driver = {
+-      .probe  = rzg2l_mipi_dsi_probe,
+-      .remove_new = rzg2l_mipi_dsi_remove,
+-      .driver = {
+-              .name = "rzg2l-mipi-dsi",
+-              .pm = &rzg2l_mipi_pm_ops,
+-              .of_match_table = rzg2l_mipi_dsi_of_table,
+-      },
+-};
+-
+-module_platform_driver(rzg2l_mipi_dsi_platform_driver);
+-
+-MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+-MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver");
+-MODULE_LICENSE("GPL");
+--- a/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h
++++ /dev/null
+@@ -1,151 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * RZ/G2L MIPI DSI Interface Registers Definitions
+- *
+- * Copyright (C) 2022 Renesas Electronics Corporation
+- */
+-
+-#ifndef __RZG2L_MIPI_DSI_REGS_H__
+-#define __RZG2L_MIPI_DSI_REGS_H__
+-
+-#include <linux/bits.h>
+-
+-/* DPHY Registers */
+-#define DSIDPHYCTRL0                  0x00
+-#define DSIDPHYCTRL0_CAL_EN_HSRX_OFS  BIT(16)
+-#define DSIDPHYCTRL0_CMN_MASTER_EN    BIT(8)
+-#define DSIDPHYCTRL0_RE_VDD_DETVCCQLV18       BIT(2)
+-#define DSIDPHYCTRL0_EN_LDO1200               BIT(1)
+-#define DSIDPHYCTRL0_EN_BGR           BIT(0)
+-
+-#define DSIDPHYTIM0                   0x04
+-#define DSIDPHYTIM0_TCLK_MISS(x)      ((x) << 24)
+-#define DSIDPHYTIM0_T_INIT(x)         ((x) << 0)
+-
+-#define DSIDPHYTIM1                   0x08
+-#define DSIDPHYTIM1_THS_PREPARE(x)    ((x) << 24)
+-#define DSIDPHYTIM1_TCLK_PREPARE(x)   ((x) << 16)
+-#define DSIDPHYTIM1_THS_SETTLE(x)     ((x) << 8)
+-#define DSIDPHYTIM1_TCLK_SETTLE(x)    ((x) << 0)
+-
+-#define DSIDPHYTIM2                   0x0c
+-#define DSIDPHYTIM2_TCLK_TRAIL(x)     ((x) << 24)
+-#define DSIDPHYTIM2_TCLK_POST(x)      ((x) << 16)
+-#define DSIDPHYTIM2_TCLK_PRE(x)               ((x) << 8)
+-#define DSIDPHYTIM2_TCLK_ZERO(x)      ((x) << 0)
+-
+-#define DSIDPHYTIM3                   0x10
+-#define DSIDPHYTIM3_TLPX(x)           ((x) << 24)
+-#define DSIDPHYTIM3_THS_EXIT(x)               ((x) << 16)
+-#define DSIDPHYTIM3_THS_TRAIL(x)      ((x) << 8)
+-#define DSIDPHYTIM3_THS_ZERO(x)               ((x) << 0)
+-
+-/* --------------------------------------------------------*/
+-/* Link Registers */
+-#define LINK_REG_OFFSET                       0x10000
+-
+-/* Link Status Register */
+-#define LINKSR                                0x10
+-#define LINKSR_LPBUSY                 BIT(13)
+-#define LINKSR_HSBUSY                 BIT(12)
+-#define LINKSR_VICHRUN1                       BIT(8)
+-#define LINKSR_SQCHRUN1                       BIT(4)
+-#define LINKSR_SQCHRUN0                       BIT(0)
+-
+-/* Tx Set Register */
+-#define TXSETR                                0x100
+-#define TXSETR_NUMLANECAP             (0x3 << 16)
+-#define TXSETR_DLEN                   (1 << 9)
+-#define TXSETR_CLEN                   (1 << 8)
+-#define TXSETR_NUMLANEUSE(x)          (((x) & 0x3) << 0)
+-
+-/* HS Clock Set Register */
+-#define HSCLKSETR                     0x104
+-#define HSCLKSETR_HSCLKMODE_CONT      (1 << 1)
+-#define HSCLKSETR_HSCLKMODE_NON_CONT  (0 << 1)
+-#define HSCLKSETR_HSCLKRUN_HS         (1 << 0)
+-#define HSCLKSETR_HSCLKRUN_LP         (0 << 0)
+-
+-/* Reset Control Register */
+-#define RSTCR                         0x110
+-#define RSTCR_SWRST                   BIT(0)
+-#define RSTCR_FCETXSTP                        BIT(16)
+-
+-/* Reset Status Register */
+-#define RSTSR                         0x114
+-#define RSTSR_DL0DIR                  (1 << 15)
+-#define RSTSR_DLSTPST                 (0xf << 8)
+-#define RSTSR_SWRSTV1                 (1 << 4)
+-#define RSTSR_SWRSTIB                 (1 << 3)
+-#define RSTSR_SWRSTAPB                        (1 << 2)
+-#define RSTSR_SWRSTLP                 (1 << 1)
+-#define RSTSR_SWRSTHS                 (1 << 0)
+-
+-/* Clock Lane Stop Time Set Register */
+-#define CLSTPTSETR                    0x314
+-#define CLSTPTSETR_CLKKPT(x)          ((x) << 24)
+-#define CLSTPTSETR_CLKBFHT(x)         ((x) << 16)
+-#define CLSTPTSETR_CLKSTPT(x)         ((x) << 2)
+-
+-/* LP Transition Time Set Register */
+-#define LPTRNSTSETR                   0x318
+-#define LPTRNSTSETR_GOLPBKT(x)                ((x) << 0)
+-
+-/* Physical Lane Status Register */
+-#define PLSR                          0x320
+-#define PLSR_CLHS2LP                  BIT(27)
+-#define PLSR_CLLP2HS                  BIT(26)
+-
+-/* Video-Input Channel 1 Set 0 Register */
+-#define VICH1SET0R                    0x400
+-#define VICH1SET0R_VSEN                       BIT(12)
+-#define VICH1SET0R_HFPNOLP            BIT(10)
+-#define VICH1SET0R_HBPNOLP            BIT(9)
+-#define VICH1SET0R_HSANOLP            BIT(8)
+-#define VICH1SET0R_VSTPAFT            BIT(1)
+-#define VICH1SET0R_VSTART             BIT(0)
+-
+-/* Video-Input Channel 1 Set 1 Register */
+-#define VICH1SET1R                    0x404
+-#define VICH1SET1R_DLY(x)             (((x) & 0xfff) << 2)
+-
+-/* Video-Input Channel 1 Status Register */
+-#define VICH1SR                               0x410
+-#define VICH1SR_VIRDY                 BIT(3)
+-#define VICH1SR_RUNNING                       BIT(2)
+-#define VICH1SR_STOP                  BIT(1)
+-#define VICH1SR_START                 BIT(0)
+-
+-/* Video-Input Channel 1 Pixel Packet Set Register */
+-#define VICH1PPSETR                   0x420
+-#define VICH1PPSETR_DT_RGB18          (0x1e << 16)
+-#define VICH1PPSETR_DT_RGB18_LS               (0x2e << 16)
+-#define VICH1PPSETR_DT_RGB24          (0x3e << 16)
+-#define VICH1PPSETR_TXESYNC_PULSE     (1 << 15)
+-#define VICH1PPSETR_VC(x)             ((x) << 22)
+-
+-/* Video-Input Channel 1 Vertical Size Set Register */
+-#define VICH1VSSETR                   0x428
+-#define VICH1VSSETR_VACTIVE(x)                (((x) & 0x7fff) << 16)
+-#define VICH1VSSETR_VSPOL_LOW         (1 << 15)
+-#define VICH1VSSETR_VSPOL_HIGH                (0 << 15)
+-#define VICH1VSSETR_VSA(x)            (((x) & 0xfff) << 0)
+-
+-/* Video-Input Channel 1 Vertical Porch Set Register */
+-#define VICH1VPSETR                   0x42c
+-#define VICH1VPSETR_VFP(x)            (((x) & 0x1fff) << 16)
+-#define VICH1VPSETR_VBP(x)            (((x) & 0x1fff) << 0)
+-
+-/* Video-Input Channel 1 Horizontal Size Set Register */
+-#define VICH1HSSETR                   0x430
+-#define VICH1HSSETR_HACTIVE(x)                (((x) & 0x7fff) << 16)
+-#define VICH1HSSETR_HSPOL_LOW         (1 << 15)
+-#define VICH1HSSETR_HSPOL_HIGH                (0 << 15)
+-#define VICH1HSSETR_HSA(x)            (((x) & 0xfff) << 0)
+-
+-/* Video-Input Channel 1 Horizontal Porch Set Register */
+-#define VICH1HPSETR                   0x434
+-#define VICH1HPSETR_HFP(x)            (((x) & 0x1fff) << 16)
+-#define VICH1HPSETR_HBP(x)            (((x) & 0x1fff) << 0)
+-
+-#endif /* __RZG2L_MIPI_DSI_REGS_H__ */
+--- /dev/null
++++ b/drivers/gpu/drm/renesas/rz-du/Kconfig
+@@ -0,0 +1,8 @@
++# SPDX-License-Identifier: GPL-2.0
++config DRM_RZG2L_MIPI_DSI
++      tristate "RZ/G2L MIPI DSI Encoder Support"
++      depends on DRM && DRM_BRIDGE && OF
++      depends on ARCH_RENESAS || COMPILE_TEST
++      select DRM_MIPI_DSI
++      help
++        Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders.
+--- /dev/null
++++ b/drivers/gpu/drm/renesas/rz-du/Makefile
+@@ -0,0 +1,3 @@
++# SPDX-License-Identifier: GPL-2.0
++
++obj-$(CONFIG_DRM_RZG2L_MIPI_DSI)      += rzg2l_mipi_dsi.o
+--- /dev/null
++++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+@@ -0,0 +1,816 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * RZ/G2L MIPI DSI Encoder Driver
++ *
++ * Copyright (C) 2022 Renesas Electronics Corporation
++ */
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_graph.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/reset.h>
++#include <linux/slab.h>
++
++#include <drm/drm_atomic.h>
++#include <drm/drm_atomic_helper.h>
++#include <drm/drm_bridge.h>
++#include <drm/drm_mipi_dsi.h>
++#include <drm/drm_of.h>
++#include <drm/drm_panel.h>
++#include <drm/drm_probe_helper.h>
++
++#include "rzg2l_mipi_dsi_regs.h"
++
++struct rzg2l_mipi_dsi {
++      struct device *dev;
++      void __iomem *mmio;
++
++      struct reset_control *rstc;
++      struct reset_control *arstc;
++      struct reset_control *prstc;
++
++      struct mipi_dsi_host host;
++      struct drm_bridge bridge;
++      struct drm_bridge *next_bridge;
++
++      struct clk *vclk;
++
++      enum mipi_dsi_pixel_format format;
++      unsigned int num_data_lanes;
++      unsigned int lanes;
++      unsigned long mode_flags;
++};
++
++static inline struct rzg2l_mipi_dsi *
++bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge)
++{
++      return container_of(bridge, struct rzg2l_mipi_dsi, bridge);
++}
++
++static inline struct rzg2l_mipi_dsi *
++host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host)
++{
++      return container_of(host, struct rzg2l_mipi_dsi, host);
++}
++
++struct rzg2l_mipi_dsi_timings {
++      unsigned long hsfreq_max;
++      u32 t_init;
++      u32 tclk_prepare;
++      u32 ths_prepare;
++      u32 tclk_zero;
++      u32 tclk_pre;
++      u32 tclk_post;
++      u32 tclk_trail;
++      u32 ths_zero;
++      u32 ths_trail;
++      u32 ths_exit;
++      u32 tlpx;
++};
++
++static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {
++      {
++              .hsfreq_max = 80000,
++              .t_init = 79801,
++              .tclk_prepare = 8,
++              .ths_prepare = 13,
++              .tclk_zero = 33,
++              .tclk_pre = 24,
++              .tclk_post = 94,
++              .tclk_trail = 10,
++              .ths_zero = 23,
++              .ths_trail = 17,
++              .ths_exit = 13,
++              .tlpx = 6,
++      },
++      {
++              .hsfreq_max = 125000,
++              .t_init = 79801,
++              .tclk_prepare = 8,
++              .ths_prepare = 12,
++              .tclk_zero = 33,
++              .tclk_pre = 15,
++              .tclk_post = 94,
++              .tclk_trail = 10,
++              .ths_zero = 23,
++              .ths_trail = 17,
++              .ths_exit = 13,
++              .tlpx = 6,
++      },
++      {
++              .hsfreq_max = 250000,
++              .t_init = 79801,
++              .tclk_prepare = 8,
++              .ths_prepare = 12,
++              .tclk_zero = 33,
++              .tclk_pre = 13,
++              .tclk_post = 94,
++              .tclk_trail = 10,
++              .ths_zero = 23,
++              .ths_trail = 16,
++              .ths_exit = 13,
++              .tlpx = 6,
++      },
++      {
++              .hsfreq_max = 360000,
++              .t_init = 79801,
++              .tclk_prepare = 8,
++              .ths_prepare = 10,
++              .tclk_zero = 33,
++              .tclk_pre = 4,
++              .tclk_post = 35,
++              .tclk_trail = 7,
++              .ths_zero = 16,
++              .ths_trail = 9,
++              .ths_exit = 13,
++              .tlpx = 6,
++      },
++      {
++              .hsfreq_max = 720000,
++              .t_init = 79801,
++              .tclk_prepare = 8,
++              .ths_prepare = 9,
++              .tclk_zero = 33,
++              .tclk_pre = 4,
++              .tclk_post = 35,
++              .tclk_trail = 7,
++              .ths_zero = 16,
++              .ths_trail = 9,
++              .ths_exit = 13,
++              .tlpx = 6,
++      },
++      {
++              .hsfreq_max = 1500000,
++              .t_init = 79801,
++              .tclk_prepare = 8,
++              .ths_prepare = 9,
++              .tclk_zero = 33,
++              .tclk_pre = 4,
++              .tclk_post = 35,
++              .tclk_trail = 7,
++              .ths_zero = 16,
++              .ths_trail = 9,
++              .ths_exit = 13,
++              .tlpx = 6,
++      },
++};
++
++static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
++{
++      iowrite32(data, dsi->mmio + reg);
++}
++
++static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
++{
++      iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);
++}
++
++static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
++{
++      return ioread32(dsi->mmio + reg);
++}
++
++static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
++{
++      return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);
++}
++
++/* -----------------------------------------------------------------------------
++ * Hardware Setup
++ */
++
++static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
++                                  unsigned long hsfreq)
++{
++      const struct rzg2l_mipi_dsi_timings *dphy_timings;
++      unsigned int i;
++      u32 dphyctrl0;
++      u32 dphytim0;
++      u32 dphytim1;
++      u32 dphytim2;
++      u32 dphytim3;
++      int ret;
++
++      /* All DSI global operation timings are set with recommended setting */
++      for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) {
++              dphy_timings = &rzg2l_mipi_dsi_global_timings[i];
++              if (hsfreq <= dphy_timings->hsfreq_max)
++                      break;
++      }
++
++      /* Initializing DPHY before accessing LINK */
++      dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN |
++                  DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR;
++
++      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
++      usleep_range(20, 30);
++
++      dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200;
++      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
++      usleep_range(10, 20);
++
++      dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) |
++                 DSIDPHYTIM0_T_INIT(dphy_timings->t_init);
++      dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) |
++                 DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) |
++                 DSIDPHYTIM1_THS_SETTLE(0) |
++                 DSIDPHYTIM1_TCLK_SETTLE(0);
++      dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) |
++                 DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) |
++                 DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) |
++                 DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero);
++      dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) |
++                 DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) |
++                 DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) |
++                 DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero);
++
++      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0);
++      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1);
++      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2);
++      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3);
++
++      ret = reset_control_deassert(dsi->rstc);
++      if (ret < 0)
++              return ret;
++
++      udelay(1);
++
++      return 0;
++}
++
++static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)
++{
++      u32 dphyctrl0;
++
++      dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0);
++
++      dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR);
++      rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
++
++      reset_control_assert(dsi->rstc);
++}
++
++static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
++                                const struct drm_display_mode *mode)
++{
++      unsigned long hsfreq;
++      unsigned int bpp;
++      u32 txsetr;
++      u32 clstptsetr;
++      u32 lptrnstsetr;
++      u32 clkkpt;
++      u32 clkbfht;
++      u32 clkstpt;
++      u32 golpbkt;
++      int ret;
++
++      /*
++       * Relationship between hsclk and vclk must follow
++       * vclk * bpp = hsclk * 8 * lanes
++       * where vclk: video clock (Hz)
++       *       bpp: video pixel bit depth
++       *       hsclk: DSI HS Byte clock frequency (Hz)
++       *       lanes: number of data lanes
++       *
++       * hsclk(bit) = hsclk(byte) * 8
++       */
++      bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
++      hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);
++
++      ret = pm_runtime_resume_and_get(dsi->dev);
++      if (ret < 0)
++              return ret;
++
++      clk_set_rate(dsi->vclk, mode->clock * 1000);
++
++      ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
++      if (ret < 0)
++              goto err_phy;
++
++      /* Enable Data lanes and Clock lanes */
++      txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN;
++      rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);
++
++      /*
++       * Global timings characteristic depends on high speed Clock Frequency
++       * Currently MIPI DSI-IF just supports maximum FHD@60 with:
++       * - videoclock = 148.5 (MHz)
++       * - bpp: maximum 24bpp
++       * - data lanes: maximum 4 lanes
++       * Therefore maximum hsclk will be 891 Mbps.
++       */
++      if (hsfreq > 445500) {
++              clkkpt = 12;
++              clkbfht = 15;
++              clkstpt = 48;
++              golpbkt = 75;
++      } else if (hsfreq > 250000) {
++              clkkpt = 7;
++              clkbfht = 8;
++              clkstpt = 27;
++              golpbkt = 40;
++      } else {
++              clkkpt = 8;
++              clkbfht = 6;
++              clkstpt = 24;
++              golpbkt = 29;
++      }
++
++      clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) |
++                   CLSTPTSETR_CLKSTPT(clkstpt);
++      rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr);
++
++      lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
++      rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
++
++      return 0;
++
++err_phy:
++      rzg2l_mipi_dsi_dphy_exit(dsi);
++      pm_runtime_put(dsi->dev);
++
++      return ret;
++}
++
++static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)
++{
++      rzg2l_mipi_dsi_dphy_exit(dsi);
++      pm_runtime_put(dsi->dev);
++}
++
++static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,
++                                            const struct drm_display_mode *mode)
++{
++      u32 vich1ppsetr;
++      u32 vich1vssetr;
++      u32 vich1vpsetr;
++      u32 vich1hssetr;
++      u32 vich1hpsetr;
++      int dsi_format;
++      u32 delay[2];
++      u8 index;
++
++      /* Configuration for Pixel Packet */
++      dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format);
++      switch (dsi_format) {
++      case 24:
++              vich1ppsetr = VICH1PPSETR_DT_RGB24;
++              break;
++      case 18:
++              vich1ppsetr = VICH1PPSETR_DT_RGB18;
++              break;
++      }
++
++      if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) &&
++          !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))
++              vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE;
++
++      rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr);
++
++      /* Configuration for Video Parameters */
++      vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) |
++                    VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start);
++      vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ?
++                      VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW;
++
++      vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) |
++                    VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end);
++
++      vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) |
++                    VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start);
++      vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ?
++                      VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW;
++
++      vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) |
++                    VICH1HPSETR_HBP(mode->htotal - mode->hsync_end);
++
++      rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr);
++      rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr);
++      rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr);
++      rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr);
++
++      /*
++       * Configuration for Delay Value
++       * Delay value based on 2 ranges of video clock.
++       * 74.25MHz is videoclock of HD@60p or FHD@30p
++       */
++      if (mode->clock > 74250) {
++              delay[0] = 231;
++              delay[1] = 216;
++      } else {
++              delay[0] = 220;
++              delay[1] = 212;
++      }
++
++      if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
++              index = 0;
++      else
++              index = 1;
++
++      rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R,
++                                VICH1SET1R_DLY(delay[index]));
++}
++
++static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi)
++{
++      bool is_clk_cont;
++      u32 hsclksetr;
++      u32 status;
++      int ret;
++
++      is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
++
++      /* Start HS clock */
++      hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ?
++                                           HSCLKSETR_HSCLKMODE_CONT :
++                                           HSCLKSETR_HSCLKMODE_NON_CONT);
++      rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr);
++
++      if (is_clk_cont) {
++              ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
++                                      status & PLSR_CLLP2HS,
++                                      2000, 20000, false, dsi, PLSR);
++              if (ret < 0) {
++                      dev_err(dsi->dev, "failed to start HS clock\n");
++                      return ret;
++              }
++      }
++
++      dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode",
++              is_clk_cont ? "continuous" : "non-continuous");
++
++      return 0;
++}
++
++static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi)
++{
++      bool is_clk_cont;
++      u32 status;
++      int ret;
++
++      is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
++
++      /* Stop HS clock */
++      rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR,
++                                is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT :
++                                HSCLKSETR_HSCLKMODE_NON_CONT);
++
++      if (is_clk_cont) {
++              ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
++                                      status & PLSR_CLHS2LP,
++                                      2000, 20000, false, dsi, PLSR);
++              if (ret < 0) {
++                      dev_err(dsi->dev, "failed to stop HS clock\n");
++                      return ret;
++              }
++      }
++
++      return 0;
++}
++
++static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi)
++{
++      u32 vich1set0r;
++      u32 status;
++      int ret;
++
++      /* Configuration for Blanking sequence and start video input*/
++      vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP |
++                   VICH1SET0R_HSANOLP | VICH1SET0R_VSTART;
++      rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r);
++
++      ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
++                              status & VICH1SR_VIRDY,
++                              2000, 20000, false, dsi, VICH1SR);
++      if (ret < 0)
++              dev_err(dsi->dev, "Failed to start video signal input\n");
++
++      return ret;
++}
++
++static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi)
++{
++      u32 status;
++      int ret;
++
++      rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT);
++      ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
++                              (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)),
++                              2000, 20000, false, dsi, VICH1SR);
++      if (ret < 0)
++              goto err;
++
++      ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
++                              !(status & LINKSR_HSBUSY),
++                              2000, 20000, false, dsi, LINKSR);
++      if (ret < 0)
++              goto err;
++
++      return 0;
++
++err:
++      dev_err(dsi->dev, "Failed to stop video signal input\n");
++      return ret;
++}
++
++/* -----------------------------------------------------------------------------
++ * Bridge
++ */
++
++static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,
++                               enum drm_bridge_attach_flags flags)
++{
++      struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
++
++      return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge,
++                               flags);
++}
++
++static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
++                                       struct drm_bridge_state *old_bridge_state)
++{
++      struct drm_atomic_state *state = old_bridge_state->base.state;
++      struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
++      const struct drm_display_mode *mode;
++      struct drm_connector *connector;
++      struct drm_crtc *crtc;
++      int ret;
++
++      connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
++      crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
++      mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
++
++      ret = rzg2l_mipi_dsi_startup(dsi, mode);
++      if (ret < 0)
++              return;
++
++      rzg2l_mipi_dsi_set_display_timing(dsi, mode);
++
++      ret = rzg2l_mipi_dsi_start_hs_clock(dsi);
++      if (ret < 0)
++              goto err_stop;
++
++      ret = rzg2l_mipi_dsi_start_video(dsi);
++      if (ret < 0)
++              goto err_stop_clock;
++
++      return;
++
++err_stop_clock:
++      rzg2l_mipi_dsi_stop_hs_clock(dsi);
++err_stop:
++      rzg2l_mipi_dsi_stop(dsi);
++}
++
++static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,
++                                        struct drm_bridge_state *old_bridge_state)
++{
++      struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
++
++      rzg2l_mipi_dsi_stop_video(dsi);
++      rzg2l_mipi_dsi_stop_hs_clock(dsi);
++      rzg2l_mipi_dsi_stop(dsi);
++}
++
++static enum drm_mode_status
++rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
++                               const struct drm_display_info *info,
++                               const struct drm_display_mode *mode)
++{
++      if (mode->clock > 148500)
++              return MODE_CLOCK_HIGH;
++
++      if (mode->clock < 5803)
++              return MODE_CLOCK_LOW;
++
++      return MODE_OK;
++}
++
++static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {
++      .attach = rzg2l_mipi_dsi_attach,
++      .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
++      .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
++      .atomic_reset = drm_atomic_helper_bridge_reset,
++      .atomic_enable = rzg2l_mipi_dsi_atomic_enable,
++      .atomic_disable = rzg2l_mipi_dsi_atomic_disable,
++      .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,
++};
++
++/* -----------------------------------------------------------------------------
++ * Host setting
++ */
++
++static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
++                                    struct mipi_dsi_device *device)
++{
++      struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
++      int ret;
++
++      if (device->lanes > dsi->num_data_lanes) {
++              dev_err(dsi->dev,
++                      "Number of lines of device (%u) exceeds host (%u)\n",
++                      device->lanes, dsi->num_data_lanes);
++              return -EINVAL;
++      }
++
++      switch (mipi_dsi_pixel_format_to_bpp(device->format)) {
++      case 24:
++      case 18:
++              break;
++      default:
++              dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format);
++              return -EINVAL;
++      }
++
++      dsi->lanes = device->lanes;
++      dsi->format = device->format;
++      dsi->mode_flags = device->mode_flags;
++
++      dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node,
++                                                1, 0);
++      if (IS_ERR(dsi->next_bridge)) {
++              ret = PTR_ERR(dsi->next_bridge);
++              dev_err(dsi->dev, "failed to get next bridge: %d\n", ret);
++              return ret;
++      }
++
++      drm_bridge_add(&dsi->bridge);
++
++      return 0;
++}
++
++static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
++                                    struct mipi_dsi_device *device)
++{
++      struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
++
++      drm_bridge_remove(&dsi->bridge);
++
++      return 0;
++}
++
++static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
++      .attach = rzg2l_mipi_dsi_host_attach,
++      .detach = rzg2l_mipi_dsi_host_detach,
++};
++
++/* -----------------------------------------------------------------------------
++ * Power Management
++ */
++
++static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev)
++{
++      struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
++
++      reset_control_assert(dsi->prstc);
++      reset_control_assert(dsi->arstc);
++
++      return 0;
++}
++
++static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev)
++{
++      struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
++      int ret;
++
++      ret = reset_control_deassert(dsi->arstc);
++      if (ret < 0)
++              return ret;
++
++      ret = reset_control_deassert(dsi->prstc);
++      if (ret < 0)
++              reset_control_assert(dsi->arstc);
++
++      return ret;
++}
++
++static const struct dev_pm_ops rzg2l_mipi_pm_ops = {
++      SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL)
++};
++
++/* -----------------------------------------------------------------------------
++ * Probe & Remove
++ */
++
++static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
++{
++      unsigned int num_data_lanes;
++      struct rzg2l_mipi_dsi *dsi;
++      u32 txsetr;
++      int ret;
++
++      dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
++      if (!dsi)
++              return -ENOMEM;
++
++      platform_set_drvdata(pdev, dsi);
++      dsi->dev = &pdev->dev;
++
++      ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4);
++      if (ret < 0)
++              return dev_err_probe(dsi->dev, ret,
++                                   "missing or invalid data-lanes property\n");
++
++      num_data_lanes = ret;
++
++      dsi->mmio = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(dsi->mmio))
++              return PTR_ERR(dsi->mmio);
++
++      dsi->vclk = devm_clk_get(dsi->dev, "vclk");
++      if (IS_ERR(dsi->vclk))
++              return PTR_ERR(dsi->vclk);
++
++      dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst");
++      if (IS_ERR(dsi->rstc))
++              return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc),
++                                   "failed to get rst\n");
++
++      dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst");
++      if (IS_ERR(dsi->arstc))
++              return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc),
++                                   "failed to get arst\n");
++
++      dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst");
++      if (IS_ERR(dsi->prstc))
++              return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc),
++                                   "failed to get prst\n");
++
++      platform_set_drvdata(pdev, dsi);
++
++      pm_runtime_enable(dsi->dev);
++
++      ret = pm_runtime_resume_and_get(dsi->dev);
++      if (ret < 0)
++              goto err_pm_disable;
++
++      /*
++       * TXSETR register can be read only after DPHY init. But during probe
++       * mode->clock and format are not available. So initialize DPHY with
++       * timing parameters for 80Mbps.
++       */
++      ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000);
++      if (ret < 0)
++              goto err_phy;
++
++      txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);
++      dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);
++      rzg2l_mipi_dsi_dphy_exit(dsi);
++      pm_runtime_put(dsi->dev);
++
++      /* Initialize the DRM bridge. */
++      dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops;
++      dsi->bridge.of_node = dsi->dev->of_node;
++
++      /* Init host device */
++      dsi->host.dev = dsi->dev;
++      dsi->host.ops = &rzg2l_mipi_dsi_host_ops;
++      ret = mipi_dsi_host_register(&dsi->host);
++      if (ret < 0)
++              goto err_pm_disable;
++
++      return 0;
++
++err_phy:
++      rzg2l_mipi_dsi_dphy_exit(dsi);
++      pm_runtime_put(dsi->dev);
++err_pm_disable:
++      pm_runtime_disable(dsi->dev);
++      return ret;
++}
++
++static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)
++{
++      struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);
++
++      mipi_dsi_host_unregister(&dsi->host);
++      pm_runtime_disable(&pdev->dev);
++}
++
++static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {
++      { .compatible = "renesas,rzg2l-mipi-dsi" },
++      { /* sentinel */ }
++};
++
++MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table);
++
++static struct platform_driver rzg2l_mipi_dsi_platform_driver = {
++      .probe  = rzg2l_mipi_dsi_probe,
++      .remove_new = rzg2l_mipi_dsi_remove,
++      .driver = {
++              .name = "rzg2l-mipi-dsi",
++              .pm = &rzg2l_mipi_pm_ops,
++              .of_match_table = rzg2l_mipi_dsi_of_table,
++      },
++};
++
++module_platform_driver(rzg2l_mipi_dsi_platform_driver);
++
++MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
++MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
+@@ -0,0 +1,151 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * RZ/G2L MIPI DSI Interface Registers Definitions
++ *
++ * Copyright (C) 2022 Renesas Electronics Corporation
++ */
++
++#ifndef __RZG2L_MIPI_DSI_REGS_H__
++#define __RZG2L_MIPI_DSI_REGS_H__
++
++#include <linux/bits.h>
++
++/* DPHY Registers */
++#define DSIDPHYCTRL0                  0x00
++#define DSIDPHYCTRL0_CAL_EN_HSRX_OFS  BIT(16)
++#define DSIDPHYCTRL0_CMN_MASTER_EN    BIT(8)
++#define DSIDPHYCTRL0_RE_VDD_DETVCCQLV18       BIT(2)
++#define DSIDPHYCTRL0_EN_LDO1200               BIT(1)
++#define DSIDPHYCTRL0_EN_BGR           BIT(0)
++
++#define DSIDPHYTIM0                   0x04
++#define DSIDPHYTIM0_TCLK_MISS(x)      ((x) << 24)
++#define DSIDPHYTIM0_T_INIT(x)         ((x) << 0)
++
++#define DSIDPHYTIM1                   0x08
++#define DSIDPHYTIM1_THS_PREPARE(x)    ((x) << 24)
++#define DSIDPHYTIM1_TCLK_PREPARE(x)   ((x) << 16)
++#define DSIDPHYTIM1_THS_SETTLE(x)     ((x) << 8)
++#define DSIDPHYTIM1_TCLK_SETTLE(x)    ((x) << 0)
++
++#define DSIDPHYTIM2                   0x0c
++#define DSIDPHYTIM2_TCLK_TRAIL(x)     ((x) << 24)
++#define DSIDPHYTIM2_TCLK_POST(x)      ((x) << 16)
++#define DSIDPHYTIM2_TCLK_PRE(x)               ((x) << 8)
++#define DSIDPHYTIM2_TCLK_ZERO(x)      ((x) << 0)
++
++#define DSIDPHYTIM3                   0x10
++#define DSIDPHYTIM3_TLPX(x)           ((x) << 24)
++#define DSIDPHYTIM3_THS_EXIT(x)               ((x) << 16)
++#define DSIDPHYTIM3_THS_TRAIL(x)      ((x) << 8)
++#define DSIDPHYTIM3_THS_ZERO(x)               ((x) << 0)
++
++/* --------------------------------------------------------*/
++/* Link Registers */
++#define LINK_REG_OFFSET                       0x10000
++
++/* Link Status Register */
++#define LINKSR                                0x10
++#define LINKSR_LPBUSY                 BIT(13)
++#define LINKSR_HSBUSY                 BIT(12)
++#define LINKSR_VICHRUN1                       BIT(8)
++#define LINKSR_SQCHRUN1                       BIT(4)
++#define LINKSR_SQCHRUN0                       BIT(0)
++
++/* Tx Set Register */
++#define TXSETR                                0x100
++#define TXSETR_NUMLANECAP             (0x3 << 16)
++#define TXSETR_DLEN                   (1 << 9)
++#define TXSETR_CLEN                   (1 << 8)
++#define TXSETR_NUMLANEUSE(x)          (((x) & 0x3) << 0)
++
++/* HS Clock Set Register */
++#define HSCLKSETR                     0x104
++#define HSCLKSETR_HSCLKMODE_CONT      (1 << 1)
++#define HSCLKSETR_HSCLKMODE_NON_CONT  (0 << 1)
++#define HSCLKSETR_HSCLKRUN_HS         (1 << 0)
++#define HSCLKSETR_HSCLKRUN_LP         (0 << 0)
++
++/* Reset Control Register */
++#define RSTCR                         0x110
++#define RSTCR_SWRST                   BIT(0)
++#define RSTCR_FCETXSTP                        BIT(16)
++
++/* Reset Status Register */
++#define RSTSR                         0x114
++#define RSTSR_DL0DIR                  (1 << 15)
++#define RSTSR_DLSTPST                 (0xf << 8)
++#define RSTSR_SWRSTV1                 (1 << 4)
++#define RSTSR_SWRSTIB                 (1 << 3)
++#define RSTSR_SWRSTAPB                        (1 << 2)
++#define RSTSR_SWRSTLP                 (1 << 1)
++#define RSTSR_SWRSTHS                 (1 << 0)
++
++/* Clock Lane Stop Time Set Register */
++#define CLSTPTSETR                    0x314
++#define CLSTPTSETR_CLKKPT(x)          ((x) << 24)
++#define CLSTPTSETR_CLKBFHT(x)         ((x) << 16)
++#define CLSTPTSETR_CLKSTPT(x)         ((x) << 2)
++
++/* LP Transition Time Set Register */
++#define LPTRNSTSETR                   0x318
++#define LPTRNSTSETR_GOLPBKT(x)                ((x) << 0)
++
++/* Physical Lane Status Register */
++#define PLSR                          0x320
++#define PLSR_CLHS2LP                  BIT(27)
++#define PLSR_CLLP2HS                  BIT(26)
++
++/* Video-Input Channel 1 Set 0 Register */
++#define VICH1SET0R                    0x400
++#define VICH1SET0R_VSEN                       BIT(12)
++#define VICH1SET0R_HFPNOLP            BIT(10)
++#define VICH1SET0R_HBPNOLP            BIT(9)
++#define VICH1SET0R_HSANOLP            BIT(8)
++#define VICH1SET0R_VSTPAFT            BIT(1)
++#define VICH1SET0R_VSTART             BIT(0)
++
++/* Video-Input Channel 1 Set 1 Register */
++#define VICH1SET1R                    0x404
++#define VICH1SET1R_DLY(x)             (((x) & 0xfff) << 2)
++
++/* Video-Input Channel 1 Status Register */
++#define VICH1SR                               0x410
++#define VICH1SR_VIRDY                 BIT(3)
++#define VICH1SR_RUNNING                       BIT(2)
++#define VICH1SR_STOP                  BIT(1)
++#define VICH1SR_START                 BIT(0)
++
++/* Video-Input Channel 1 Pixel Packet Set Register */
++#define VICH1PPSETR                   0x420
++#define VICH1PPSETR_DT_RGB18          (0x1e << 16)
++#define VICH1PPSETR_DT_RGB18_LS               (0x2e << 16)
++#define VICH1PPSETR_DT_RGB24          (0x3e << 16)
++#define VICH1PPSETR_TXESYNC_PULSE     (1 << 15)
++#define VICH1PPSETR_VC(x)             ((x) << 22)
++
++/* Video-Input Channel 1 Vertical Size Set Register */
++#define VICH1VSSETR                   0x428
++#define VICH1VSSETR_VACTIVE(x)                (((x) & 0x7fff) << 16)
++#define VICH1VSSETR_VSPOL_LOW         (1 << 15)
++#define VICH1VSSETR_VSPOL_HIGH                (0 << 15)
++#define VICH1VSSETR_VSA(x)            (((x) & 0xfff) << 0)
++
++/* Video-Input Channel 1 Vertical Porch Set Register */
++#define VICH1VPSETR                   0x42c
++#define VICH1VPSETR_VFP(x)            (((x) & 0x1fff) << 16)
++#define VICH1VPSETR_VBP(x)            (((x) & 0x1fff) << 0)
++
++/* Video-Input Channel 1 Horizontal Size Set Register */
++#define VICH1HSSETR                   0x430
++#define VICH1HSSETR_HACTIVE(x)                (((x) & 0x7fff) << 16)
++#define VICH1HSSETR_HSPOL_LOW         (1 << 15)
++#define VICH1HSSETR_HSPOL_HIGH                (0 << 15)
++#define VICH1HSSETR_HSA(x)            (((x) & 0xfff) << 0)
++
++/* Video-Input Channel 1 Horizontal Porch Set Register */
++#define VICH1HPSETR                   0x434
++#define VICH1HPSETR_HFP(x)            (((x) & 0x1fff) << 16)
++#define VICH1HPSETR_HBP(x)            (((x) & 0x1fff) << 0)
++
++#endif /* __RZG2L_MIPI_DSI_REGS_H__ */
diff --git a/queue-6.6/drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch b/queue-6.6/drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch
new file mode 100644 (file)
index 0000000..d72ba09
--- /dev/null
@@ -0,0 +1,40 @@
+From stable+bounces-293838-greg=kroah.com@vger.kernel.org Thu Jul 30 21:39:33 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 15:29:55 -0400
+Subject: drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay
+To: stable@vger.kernel.org
+Cc: Biju Das <biju.das.jz@bp.renesas.com>, Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260730192955.3124753-2-sashal@kernel.org>
+
+From: Biju Das <biju.das.jz@bp.renesas.com>
+
+[ Upstream commit 7cbba8a8ba0219a267844d3116dbc77cecb4fcf8 ]
+
+The RZ/G2L hardware manual (Rev. 1.50, May 2025), Section 34.4.2.1,
+requires waiting at least 1 msec after deasserting the CMN_RSTB signal
+before the DSI-Tx module is ready. Increase the delay from 1 usec to
+1 msec by replacing udelay(1) with fsleep(1000) for RZ/G2L SoCs.
+
+Fixes: 7a043f978ed1 ("drm: rcar-du: Add RZ/G2L DSI driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
+Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
+Link: https://patch.msgid.link/20260330104450.128512-3-biju.das.jz@bp.renesas.com
+Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
++++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+@@ -238,7 +238,7 @@ static int rzg2l_mipi_dsi_dphy_init(stru
+       if (ret < 0)
+               return ret;
+-      udelay(1);
++      fsleep(1000);
+       return 0;
+ }
diff --git a/queue-6.6/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch b/queue-6.6/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch
new file mode 100644 (file)
index 0000000..be64e37
--- /dev/null
@@ -0,0 +1,61 @@
+From stable+bounces-294127-greg=kroah.com@vger.kernel.org Fri Jul 31 18:00:34 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 11:50:20 -0400
+Subject: drm/tegra: fbdev: Remove offset into framebuffer memory
+To: stable@vger.kernel.org
+Cc: Thomas Zimmermann <tzimmermann@suse.de>, dri-devel@lists.freedesktop.org, linux-tegra@vger.kernel.org, Thierry Reding <treding@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260731155020.604703-2-sashal@kernel.org>
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit a18b6e30ecd69096beda4a0c96d2570900c3879a ]
+
+The screen_buffer field in struct fb_info contains the kernel address
+of the first byte of framebuffer memory. Do not add the display offset.
+This offset only describes scrolling during scanout.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Fixes: de2ba664c30f ("gpu: host1x: drm: Add memory manager and fb")
+Cc: dri-devel@lists.freedesktop.org
+Cc: linux-tegra@vger.kernel.org
+Cc: <stable@vger.kernel.org> # v3.10+
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Link: https://patch.msgid.link/20260421073646.144712-3-tzimmermann@suse.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/tegra/fbdev.c |    8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/tegra/fbdev.c
++++ b/drivers/gpu/drm/tegra/fbdev.c
+@@ -75,7 +75,6 @@ static int tegra_fbdev_probe(struct drm_
+       struct fb_info *info = helper->info;
+       unsigned int bytes_per_pixel;
+       struct drm_framebuffer *fb;
+-      unsigned long offset;
+       struct tegra_bo *bo;
+       size_t size;
+       int err;
+@@ -112,9 +111,6 @@ static int tegra_fbdev_probe(struct drm_
+       drm_fb_helper_fill_info(info, helper, sizes);
+-      offset = info->var.xoffset * bytes_per_pixel +
+-               info->var.yoffset * fb->pitches[0];
+-
+       if (bo->pages) {
+               bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP,
+                                pgprot_writecombine(PAGE_KERNEL));
+@@ -126,9 +122,9 @@ static int tegra_fbdev_probe(struct drm_
+       }
+       info->flags |= FBINFO_VIRTFB;
+-      info->screen_buffer = bo->vaddr + offset;
++      info->screen_buffer = bo->vaddr;
+       info->screen_size = size;
+-      info->fix.smem_start = (unsigned long)(bo->iova + offset);
++      info->fix.smem_start = (unsigned long)(bo->iova);
+       info->fix.smem_len = size;
+       return 0;
diff --git a/queue-6.6/libceph-add-doutc-and-_client-debug-macros-support.patch b/queue-6.6/libceph-add-doutc-and-_client-debug-macros-support.patch
new file mode 100644 (file)
index 0000000..392988e
--- /dev/null
@@ -0,0 +1,91 @@
+From stable+bounces-297277-greg=kroah.com@vger.kernel.org Fri Aug  7 13:51:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  7 Aug 2026 07:48:06 -0400
+Subject: libceph: add doutc and *_client debug macros support
+To: stable@vger.kernel.org
+Cc: Xiubo Li <xiubli@redhat.com>, Patrick Donnelly <pdonnell@redhat.com>, Milind Changire <mchangir@redhat.com>, Ilya Dryomov <idryomov@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807114809.2056244-1-sashal@kernel.org>
+
+From: Xiubo Li <xiubli@redhat.com>
+
+[ Upstream commit 5c5f0d2b5f92c47baf82b9b211e27edd7d195158 ]
+
+This will help print the fsid and client's global_id in debug logs,
+and also print the function names.
+
+[ idryomov: %lld -> %llu, leading space for doutc(), don't include
+  __func__ in pr_*() variants ]
+
+Link: https://tracker.ceph.com/issues/61590
+Signed-off-by: Xiubo Li <xiubli@redhat.com>
+Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
+Reviewed-by: Milind Changire <mchangir@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Stable-dep-of: c3e64079d8b9 ("ceph: fix refcount leak in ceph_readdir()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/ceph/ceph_debug.h |   38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+--- a/include/linux/ceph/ceph_debug.h
++++ b/include/linux/ceph/ceph_debug.h
+@@ -19,12 +19,25 @@
+       pr_debug("%.*s %12.12s:%-4d : " fmt,                            \
+                8 - (int)sizeof(KBUILD_MODNAME), "    ",               \
+                kbasename(__FILE__), __LINE__, ##__VA_ARGS__)
++#  define doutc(client, fmt, ...)                                     \
++      pr_debug("%.*s %12.12s:%-4d : [%pU %llu] " fmt,                 \
++               8 - (int)sizeof(KBUILD_MODNAME), "    ",               \
++               kbasename(__FILE__), __LINE__,                         \
++               &client->fsid, client->monc.auth->global_id,           \
++               ##__VA_ARGS__)
+ # else
+ /* faux printk call just to see any compiler warnings. */
+ #  define dout(fmt, ...)      do {                            \
+               if (0)                                          \
+                       printk(KERN_DEBUG fmt, ##__VA_ARGS__);  \
+       } while (0)
++#  define doutc(client, fmt, ...)     do {                    \
++              if (0)                                          \
++                      printk(KERN_DEBUG "[%pU %llu] " fmt,    \
++                      &client->fsid,                          \
++                      client->monc.auth->global_id,           \
++                      ##__VA_ARGS__);                         \
++              } while (0)
+ # endif
+ #else
+@@ -33,7 +46,32 @@
+  * or, just wrap pr_debug
+  */
+ # define dout(fmt, ...)       pr_debug(" " fmt, ##__VA_ARGS__)
++# define doutc(client, fmt, ...)                                      \
++      pr_debug(" [%pU %llu] %s: " fmt, &client->fsid,                 \
++               client->monc.auth->global_id, __func__, ##__VA_ARGS__)
+ #endif
++#define pr_notice_client(client, fmt, ...)                            \
++      pr_notice("[%pU %llu]: " fmt, &client->fsid,                    \
++                client->monc.auth->global_id, ##__VA_ARGS__)
++#define pr_info_client(client, fmt, ...)                              \
++      pr_info("[%pU %llu]: " fmt, &client->fsid,                      \
++              client->monc.auth->global_id, ##__VA_ARGS__)
++#define pr_warn_client(client, fmt, ...)                              \
++      pr_warn("[%pU %llu]: " fmt, &client->fsid,                      \
++              client->monc.auth->global_id, ##__VA_ARGS__)
++#define pr_warn_once_client(client, fmt, ...)                         \
++      pr_warn_once("[%pU %llu]: " fmt, &client->fsid,                 \
++                   client->monc.auth->global_id, ##__VA_ARGS__)
++#define pr_err_client(client, fmt, ...)                                       \
++      pr_err("[%pU %llu]: " fmt, &client->fsid,                       \
++             client->monc.auth->global_id, ##__VA_ARGS__)
++#define pr_warn_ratelimited_client(client, fmt, ...)                  \
++      pr_warn_ratelimited("[%pU %llu]: " fmt, &client->fsid,          \
++                          client->monc.auth->global_id, ##__VA_ARGS__)
++#define pr_err_ratelimited_client(client, fmt, ...)                   \
++      pr_err_ratelimited("[%pU %llu]: " fmt, &client->fsid,           \
++                         client->monc.auth->global_id, ##__VA_ARGS__)
++
+ #endif
diff --git a/queue-6.6/media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch b/queue-6.6/media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch
new file mode 100644 (file)
index 0000000..439ebc5
--- /dev/null
@@ -0,0 +1,62 @@
+From stable+bounces-295114-greg=kroah.com@vger.kernel.org Tue Aug  4 13:08:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  4 Aug 2026 06:47:31 -0400
+Subject: media: i2c: imx219: Access height from active format in imx219_set_ctrl
+To: stable@vger.kernel.org
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Jacopo Mondi <jacopo.mondi@ideasonboard.com>, Dave Stevenson <dave.stevenson@raspberrypi.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, Hans Verkuil <hverkuil-cisco@xs4all.nl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260804104737.2827302-1-sashal@kernel.org>
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+[ Upstream commit aa86ac42eec4dd7e987c12390a0a487187e2d9ae ]
+
+Use the active format height instead of the mode height in
+imx219_set_ctrl(). This prepares for dropping the mode field from the
+imx219 structure.
+
+The state is retrieved using v4l2_subdev_get_locked_active_state() as
+the subdev active state and the control handler share the same lock.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/i2c/imx219.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -500,13 +500,18 @@ static int imx219_set_ctrl(struct v4l2_c
+       struct imx219 *imx219 =
+               container_of(ctrl->handler, struct imx219, ctrl_handler);
+       struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      const struct v4l2_mbus_framefmt *format;
++      struct v4l2_subdev_state *state;
+       int ret = 0;
++      state = v4l2_subdev_get_locked_active_state(&imx219->sd);
++      format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0);
++
+       if (ctrl->id == V4L2_CID_VBLANK) {
+               int exposure_max, exposure_def;
+               /* Update max exposure while meeting expected vblanking */
+-              exposure_max = imx219->mode->height + ctrl->val - 4;
++              exposure_max = format->height + ctrl->val - 4;
+               exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
+                       exposure_max : IMX219_EXPOSURE_DEFAULT;
+               __v4l2_ctrl_modify_range(imx219->exposure,
+@@ -546,7 +551,7 @@ static int imx219_set_ctrl(struct v4l2_c
+               break;
+       case V4L2_CID_VBLANK:
+               cci_write(imx219->regmap, IMX219_REG_VTS,
+-                        imx219->mode->height + ctrl->val, &ret);
++                        format->height + ctrl->val, &ret);
+               break;
+       case V4L2_CID_TEST_PATTERN_RED:
+               cci_write(imx219->regmap, IMX219_REG_TESTP_RED,
diff --git a/queue-6.6/media-i2c-imx219-calculate-crop-rectangle-dynamically.patch b/queue-6.6/media-i2c-imx219-calculate-crop-rectangle-dynamically.patch
new file mode 100644 (file)
index 0000000..e4c13be
--- /dev/null
@@ -0,0 +1,131 @@
+From stable+bounces-295119-greg=kroah.com@vger.kernel.org Tue Aug  4 12:57:41 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  4 Aug 2026 06:47:35 -0400
+Subject: media: i2c: imx219: Calculate crop rectangle dynamically
+To: stable@vger.kernel.org
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Jacopo Mondi <jacopo.mondi@ideasonboard.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, Hans Verkuil <hverkuil-cisco@xs4all.nl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260804104737.2827302-5-sashal@kernel.org>
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+[ Upstream commit 0af46fbc333d1a52c72823d935590410357bab47 ]
+
+Calculate the crop rectangle size and location dynamically when setting
+the format, instead of storing it in the imx219_mode structure. This
+removes duplicated information from the mode, to guarantee consistency.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/i2c/imx219.c |   45 +++++++++++++++------------------------------
+ 1 file changed, 15 insertions(+), 30 deletions(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -18,6 +18,7 @@
+ #include <linux/delay.h>
+ #include <linux/gpio/consumer.h>
+ #include <linux/i2c.h>
++#include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+@@ -161,9 +162,6 @@ struct imx219_mode {
+       /* Frame height */
+       unsigned int height;
+-      /* Analog crop rectangle. */
+-      struct v4l2_rect crop;
+-
+       /* V-timing */
+       unsigned int vts_def;
+@@ -365,12 +363,6 @@ static const struct imx219_mode supporte
+               /* 8MPix 15fps mode */
+               .width = 3280,
+               .height = 2464,
+-              .crop = {
+-                      .left = IMX219_PIXEL_ARRAY_LEFT,
+-                      .top = IMX219_PIXEL_ARRAY_TOP,
+-                      .width = 3280,
+-                      .height = 2464
+-              },
+               .vts_def = 3526,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
+@@ -382,12 +374,6 @@ static const struct imx219_mode supporte
+               /* 1080P 30fps cropped */
+               .width = 1920,
+               .height = 1080,
+-              .crop = {
+-                      .left = 688,
+-                      .top = 700,
+-                      .width = 1920,
+-                      .height = 1080
+-              },
+               .vts_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
+@@ -399,12 +385,6 @@ static const struct imx219_mode supporte
+               /* 2x2 binned 30fps mode */
+               .width = 1640,
+               .height = 1232,
+-              .crop = {
+-                      .left = IMX219_PIXEL_ARRAY_LEFT,
+-                      .top = IMX219_PIXEL_ARRAY_TOP,
+-                      .width = 3280,
+-                      .height = 2464
+-              },
+               .vts_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
+@@ -416,12 +396,6 @@ static const struct imx219_mode supporte
+               /* 640x480 30fps mode */
+               .width = 640,
+               .height = 480,
+-              .crop = {
+-                      .left = 1008,
+-                      .top = 760,
+-                      .width = 1280,
+-                      .height = 960
+-              },
+               .vts_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_640_480_regs),
+@@ -966,6 +940,7 @@ static int imx219_set_pad_format(struct
+       int exposure_max, exposure_def, hblank;
+       struct v4l2_mbus_framefmt *format;
+       struct v4l2_rect *crop;
++      unsigned int bin_h, bin_v;
+       mode = v4l2_find_nearest_size(supported_modes,
+                                     ARRAY_SIZE(supported_modes),
+@@ -975,10 +950,20 @@ static int imx219_set_pad_format(struct
+       imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code);
+       format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
+-      crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0);
+-
+       *format = fmt->format;
+-      *crop = mode->crop;
++
++      /*
++       * Use binning to maximize the crop rectangle size, and centre it in the
++       * sensor.
++       */
++      bin_h = min(IMX219_PIXEL_ARRAY_WIDTH / format->width, 2U);
++      bin_v = min(IMX219_PIXEL_ARRAY_HEIGHT / format->height, 2U);
++
++      crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0);
++      crop->width = format->width * bin_h;
++      crop->height = format->height * bin_v;
++      crop->left = (IMX219_NATIVE_WIDTH - crop->width) / 2;
++      crop->top = (IMX219_NATIVE_HEIGHT - crop->height) / 2;
+       if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+               imx219->mode = mode;
diff --git a/queue-6.6/media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch b/queue-6.6/media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch
new file mode 100644 (file)
index 0000000..8df6f8a
--- /dev/null
@@ -0,0 +1,71 @@
+From stable+bounces-295115-greg=kroah.com@vger.kernel.org Tue Aug  4 14:11:26 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  4 Aug 2026 06:47:32 -0400
+Subject: media: i2c: imx219: Don't store the current mode in the imx219 structure
+To: stable@vger.kernel.org
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Jacopo Mondi <jacopo.mondi@ideasonboard.com>, Dave Stevenson <dave.stevenson@raspberrypi.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, Hans Verkuil <hverkuil-cisco@xs4all.nl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260804104737.2827302-2-sashal@kernel.org>
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+[ Upstream commit e3e5d172d5fce9151bc101427554a158d4759856 ]
+
+The mode field of the imx219 structure is only used in
+imx219_init_controls(), after the probe function sets it to point to the
+default mode. Use the default mode directly when initializing controls,
+and drop the mode field from the imx219 structure.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/i2c/imx219.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -1067,8 +1067,8 @@ static unsigned long imx219_get_pixel_ra
+ static int imx219_init_controls(struct imx219 *imx219)
+ {
+       struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      const struct imx219_mode *mode = &supported_modes[0];
+       struct v4l2_ctrl_handler *ctrl_hdlr;
+-      unsigned int height = imx219->mode->height;
+       struct v4l2_fwnode_device_properties props;
+       int exposure_max, exposure_def, hblank;
+       int i, ret;
+@@ -1097,15 +1097,15 @@ static int imx219_init_controls(struct i
+       /* Initial vblank/hblank/exposure parameters based on current mode */
+       imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+                                          V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
+-                                         IMX219_VTS_MAX - height, 1,
+-                                         imx219->mode->vts_def - height);
+-      hblank = IMX219_PPL_DEFAULT - imx219->mode->width;
++                                         IMX219_VTS_MAX - mode->height, 1,
++                                         mode->vts_def - mode->height);
++      hblank = IMX219_PPL_DEFAULT - mode->width;
+       imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+                                          V4L2_CID_HBLANK, hblank, hblank,
+                                          1, hblank);
+       if (imx219->hblank)
+               imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+-      exposure_max = imx219->mode->vts_def - 4;
++      exposure_max = mode->vts_def - 4;
+       exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
+               exposure_max : IMX219_EXPOSURE_DEFAULT;
+       imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+@@ -1298,7 +1298,8 @@ static int imx219_probe(struct i2c_clien
+       /* Set default mode to max resolution */
+       imx219->mode = &supported_modes[0];
+-      /* sensor doesn't enter LP-11 state upon power up until and unless
++      /*
++       * Sensor doesn't enter LP-11 state upon power up until and unless
+        * streaming is started, so upon power up switch the modes to:
+        * streaming -> standby
+        */
diff --git a/queue-6.6/media-i2c-imx219-drop-imx219_vts_-macros.patch b/queue-6.6/media-i2c-imx219-drop-imx219_vts_-macros.patch
new file mode 100644 (file)
index 0000000..0265ce8
--- /dev/null
@@ -0,0 +1,88 @@
+From stable+bounces-295116-greg=kroah.com@vger.kernel.org Tue Aug  4 13:08:30 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  4 Aug 2026 06:47:33 -0400
+Subject: media: i2c: imx219: Drop IMX219_VTS_* macros
+To: stable@vger.kernel.org
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Dave Stevenson <dave.stevenson@raspberrypi.com>, Jacopo Mondi <jacopo.mondi@ideasonboard.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, Hans Verkuil <hverkuil-cisco@xs4all.nl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260804104737.2827302-3-sashal@kernel.org>
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+[ Upstream commit 5ebbdd7aab3321e60a8be23aac1fee4f16644021 ]
+
+The IMX219_VTS_* macros define default VTS values for the modes
+supported by the driver. They are used in a single place, and hinder
+readability compared to using the value directly as a decimal number.
+Drop them.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/i2c/imx219.c |   18 ++++--------------
+ 1 file changed, 4 insertions(+), 14 deletions(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -71,20 +71,10 @@
+ /* V_TIMING internal */
+ #define IMX219_REG_VTS                        CCI_REG16(0x0160)
+-#define IMX219_VTS_15FPS              0x0dc6
+-#define IMX219_VTS_30FPS_1080P                0x06e3
+-#define IMX219_VTS_30FPS_BINNED               0x06e3
+-#define IMX219_VTS_30FPS_640x480      0x06e3
+ #define IMX219_VTS_MAX                        0xffff
+ #define IMX219_VBLANK_MIN             32
+-/*Frame Length Line*/
+-#define IMX219_FLL_MIN                        0x08a6
+-#define IMX219_FLL_MAX                        0xffff
+-#define IMX219_FLL_STEP                       1
+-#define IMX219_FLL_DEFAULT            0x0c98
+-
+ /* HBLANK control - read only */
+ #define IMX219_PPL_DEFAULT            3448
+@@ -381,7 +371,7 @@ static const struct imx219_mode supporte
+                       .width = 3280,
+                       .height = 2464
+               },
+-              .vts_def = IMX219_VTS_15FPS,
++              .vts_def = 3526,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
+                       .regs = mode_3280x2464_regs,
+@@ -398,7 +388,7 @@ static const struct imx219_mode supporte
+                       .width = 1920,
+                       .height = 1080
+               },
+-              .vts_def = IMX219_VTS_30FPS_1080P,
++              .vts_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
+                       .regs = mode_1920_1080_regs,
+@@ -415,7 +405,7 @@ static const struct imx219_mode supporte
+                       .width = 3280,
+                       .height = 2464
+               },
+-              .vts_def = IMX219_VTS_30FPS_BINNED,
++              .vts_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
+                       .regs = mode_1640_1232_regs,
+@@ -432,7 +422,7 @@ static const struct imx219_mode supporte
+                       .width = 1280,
+                       .height = 960
+               },
+-              .vts_def = IMX219_VTS_30FPS_640x480,
++              .vts_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_640_480_regs),
+                       .regs = mode_640_480_regs,
diff --git a/queue-6.6/media-i2c-imx219-group-functions-by-purpose.patch b/queue-6.6/media-i2c-imx219-group-functions-by-purpose.patch
new file mode 100644 (file)
index 0000000..275dc4a
--- /dev/null
@@ -0,0 +1,673 @@
+From stable+bounces-295117-greg=kroah.com@vger.kernel.org Tue Aug  4 12:57:32 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  4 Aug 2026 06:47:34 -0400
+Subject: media: i2c: imx219: Group functions by purpose
+To: stable@vger.kernel.org
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Dave Stevenson <dave.stevenson@raspberrypi.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, Hans Verkuil <hverkuil-cisco@xs4all.nl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260804104737.2827302-4-sashal@kernel.org>
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+[ Upstream commit d03dfb7d4c5fae0d3f297536063e00ea2c1129d5 ]
+
+Move functions around to group them by purpose, in order to improve
+readability. No functional change is intended.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/i2c/imx219.c |  580 +++++++++++++++++++++++----------------------
+ 1 file changed, 298 insertions(+), 282 deletions(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -485,6 +485,10 @@ static u32 imx219_get_format_code(struct
+       return imx219_mbus_formats[i];
+ }
++/* -----------------------------------------------------------------------------
++ * Controls
++ */
++
+ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
+ {
+       struct imx219 *imx219 =
+@@ -576,130 +580,135 @@ static const struct v4l2_ctrl_ops imx219
+       .s_ctrl = imx219_set_ctrl,
+ };
+-static void imx219_update_pad_format(struct imx219 *imx219,
+-                                   const struct imx219_mode *mode,
+-                                   struct v4l2_mbus_framefmt *fmt, u32 code)
++static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
+ {
+-      /* Bayer order varies with flips */
+-      fmt->code = imx219_get_format_code(imx219, code);
+-      fmt->width = mode->width;
+-      fmt->height = mode->height;
+-      fmt->field = V4L2_FIELD_NONE;
+-      fmt->colorspace = V4L2_COLORSPACE_RAW;
+-      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+-      fmt->xfer_func = V4L2_XFER_FUNC_NONE;
++      return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE;
+ }
+-static int imx219_init_cfg(struct v4l2_subdev *sd,
+-                         struct v4l2_subdev_state *state)
++/* Initialize control handlers */
++static int imx219_init_controls(struct imx219 *imx219)
+ {
+-      struct imx219 *imx219 = to_imx219(sd);
+-      struct v4l2_mbus_framefmt *format;
+-      struct v4l2_rect *crop;
+-
+-      /* Initialize the format. */
+-      format = v4l2_subdev_get_pad_format(sd, state, 0);
+-      imx219_update_pad_format(imx219, &supported_modes[0], format,
+-                               MEDIA_BUS_FMT_SRGGB10_1X10);
+-
+-      /* Initialize the crop rectangle. */
+-      crop = v4l2_subdev_get_pad_crop(sd, state, 0);
+-      crop->top = IMX219_PIXEL_ARRAY_TOP;
+-      crop->left = IMX219_PIXEL_ARRAY_LEFT;
+-      crop->width = IMX219_PIXEL_ARRAY_WIDTH;
+-      crop->height = IMX219_PIXEL_ARRAY_HEIGHT;
++      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
++      const struct imx219_mode *mode = &supported_modes[0];
++      struct v4l2_ctrl_handler *ctrl_hdlr;
++      struct v4l2_fwnode_device_properties props;
++      int exposure_max, exposure_def, hblank;
++      int i, ret;
+-      return 0;
+-}
++      ctrl_hdlr = &imx219->ctrl_handler;
++      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
++      if (ret)
++              return ret;
+-static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
+-                               struct v4l2_subdev_state *sd_state,
+-                               struct v4l2_subdev_mbus_code_enum *code)
+-{
+-      struct imx219 *imx219 = to_imx219(sd);
++      /* By default, PIXEL_RATE is read only */
++      imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
++                                             V4L2_CID_PIXEL_RATE,
++                                             imx219_get_pixel_rate(imx219),
++                                             imx219_get_pixel_rate(imx219), 1,
++                                             imx219_get_pixel_rate(imx219));
+-      if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4))
+-              return -EINVAL;
++      imx219->link_freq =
++              v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops,
++                                     V4L2_CID_LINK_FREQ,
++                                     ARRAY_SIZE(imx219_link_freq_menu) - 1, 0,
++                                     (imx219->lanes == 2) ? imx219_link_freq_menu :
++                                     imx219_link_freq_4lane_menu);
++      if (imx219->link_freq)
++              imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+-      code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]);
++      /* Initial vblank/hblank/exposure parameters based on current mode */
++      imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
++                                         V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
++                                         IMX219_VTS_MAX - mode->height, 1,
++                                         mode->vts_def - mode->height);
++      hblank = IMX219_PPL_DEFAULT - mode->width;
++      imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
++                                         V4L2_CID_HBLANK, hblank, hblank,
++                                         1, hblank);
++      if (imx219->hblank)
++              imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++      exposure_max = mode->vts_def - 4;
++      exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
++              exposure_max : IMX219_EXPOSURE_DEFAULT;
++      imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
++                                           V4L2_CID_EXPOSURE,
++                                           IMX219_EXPOSURE_MIN, exposure_max,
++                                           IMX219_EXPOSURE_STEP,
++                                           exposure_def);
+-      return 0;
+-}
++      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
++                        IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX,
++                        IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT);
+-static int imx219_enum_frame_size(struct v4l2_subdev *sd,
+-                                struct v4l2_subdev_state *sd_state,
+-                                struct v4l2_subdev_frame_size_enum *fse)
+-{
+-      struct imx219 *imx219 = to_imx219(sd);
+-      u32 code;
++      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
++                        IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX,
++                        IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT);
+-      if (fse->index >= ARRAY_SIZE(supported_modes))
+-              return -EINVAL;
++      imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
++                                        V4L2_CID_HFLIP, 0, 1, 1, 0);
++      if (imx219->hflip)
++              imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+-      code = imx219_get_format_code(imx219, fse->code);
+-      if (fse->code != code)
+-              return -EINVAL;
++      imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
++                                        V4L2_CID_VFLIP, 0, 1, 1, 0);
++      if (imx219->vflip)
++              imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+-      fse->min_width = supported_modes[fse->index].width;
+-      fse->max_width = fse->min_width;
+-      fse->min_height = supported_modes[fse->index].height;
+-      fse->max_height = fse->min_height;
++      v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops,
++                                   V4L2_CID_TEST_PATTERN,
++                                   ARRAY_SIZE(imx219_test_pattern_menu) - 1,
++                                   0, 0, imx219_test_pattern_menu);
++      for (i = 0; i < 4; i++) {
++              /*
++               * The assumption is that
++               * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1
++               * V4L2_CID_TEST_PATTERN_BLUE   == V4L2_CID_TEST_PATTERN_RED + 2
++               * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3
++               */
++              v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
++                                V4L2_CID_TEST_PATTERN_RED + i,
++                                IMX219_TESTP_COLOUR_MIN,
++                                IMX219_TESTP_COLOUR_MAX,
++                                IMX219_TESTP_COLOUR_STEP,
++                                IMX219_TESTP_COLOUR_MAX);
++              /* The "Solid color" pattern is white by default */
++      }
+-      return 0;
+-}
++      if (ctrl_hdlr->error) {
++              ret = ctrl_hdlr->error;
++              dev_err(&client->dev, "%s control init failed (%d)\n",
++                      __func__, ret);
++              goto error;
++      }
+-static int imx219_set_pad_format(struct v4l2_subdev *sd,
+-                               struct v4l2_subdev_state *sd_state,
+-                               struct v4l2_subdev_format *fmt)
+-{
+-      struct imx219 *imx219 = to_imx219(sd);
+-      const struct imx219_mode *mode;
+-      int exposure_max, exposure_def, hblank;
+-      struct v4l2_mbus_framefmt *format;
+-      struct v4l2_rect *crop;
++      ret = v4l2_fwnode_device_parse(&client->dev, &props);
++      if (ret)
++              goto error;
+-      mode = v4l2_find_nearest_size(supported_modes,
+-                                    ARRAY_SIZE(supported_modes),
+-                                    width, height,
+-                                    fmt->format.width, fmt->format.height);
++      ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops,
++                                            &props);
++      if (ret)
++              goto error;
+-      imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code);
++      imx219->sd.ctrl_handler = ctrl_hdlr;
+-      format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
+-      crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0);
++      return 0;
+-      *format = fmt->format;
+-      *crop = mode->crop;
++error:
++      v4l2_ctrl_handler_free(ctrl_hdlr);
+-      if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+-              imx219->mode = mode;
+-              /* Update limits and set FPS to default */
+-              __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
+-                                       IMX219_VTS_MAX - mode->height, 1,
+-                                       mode->vts_def - mode->height);
+-              __v4l2_ctrl_s_ctrl(imx219->vblank,
+-                                 mode->vts_def - mode->height);
+-              /* Update max exposure while meeting expected vblanking */
+-              exposure_max = mode->vts_def - 4;
+-              exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
+-                      exposure_max : IMX219_EXPOSURE_DEFAULT;
+-              __v4l2_ctrl_modify_range(imx219->exposure,
+-                                       imx219->exposure->minimum,
+-                                       exposure_max, imx219->exposure->step,
+-                                       exposure_def);
+-              /*
+-               * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank
+-               * depends on mode->width only, and is not changeble in any
+-               * way other than changing the mode.
+-               */
+-              hblank = IMX219_PPL_DEFAULT - mode->width;
+-              __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1,
+-                                       hblank);
+-      }
++      return ret;
++}
+-      return 0;
++static void imx219_free_controls(struct imx219 *imx219)
++{
++      v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
+ }
++/* -----------------------------------------------------------------------------
++ * Subdev operations
++ */
++
+ static int imx219_set_framefmt(struct imx219 *imx219,
+                              const struct v4l2_mbus_framefmt *format)
+ {
+@@ -748,37 +757,6 @@ static int imx219_set_binning(struct imx
+       return -EINVAL;
+ }
+-static int imx219_get_selection(struct v4l2_subdev *sd,
+-                              struct v4l2_subdev_state *sd_state,
+-                              struct v4l2_subdev_selection *sel)
+-{
+-      switch (sel->target) {
+-      case V4L2_SEL_TGT_CROP: {
+-              sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0);
+-              return 0;
+-      }
+-
+-      case V4L2_SEL_TGT_NATIVE_SIZE:
+-              sel->r.top = 0;
+-              sel->r.left = 0;
+-              sel->r.width = IMX219_NATIVE_WIDTH;
+-              sel->r.height = IMX219_NATIVE_HEIGHT;
+-
+-              return 0;
+-
+-      case V4L2_SEL_TGT_CROP_DEFAULT:
+-      case V4L2_SEL_TGT_CROP_BOUNDS:
+-              sel->r.top = IMX219_PIXEL_ARRAY_TOP;
+-              sel->r.left = IMX219_PIXEL_ARRAY_LEFT;
+-              sel->r.width = IMX219_PIXEL_ARRAY_WIDTH;
+-              sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT;
+-
+-              return 0;
+-      }
+-
+-      return -EINVAL;
+-}
+-
+ static int imx219_configure_lanes(struct imx219 *imx219)
+ {
+       return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE,
+@@ -907,6 +885,190 @@ unlock:
+ }
+ /* Power/clock management functions */
++static void imx219_update_pad_format(struct imx219 *imx219,
++                                   const struct imx219_mode *mode,
++                                   struct v4l2_mbus_framefmt *fmt, u32 code)
++{
++      /* Bayer order varies with flips */
++      fmt->code = imx219_get_format_code(imx219, code);
++      fmt->width = mode->width;
++      fmt->height = mode->height;
++      fmt->field = V4L2_FIELD_NONE;
++      fmt->colorspace = V4L2_COLORSPACE_RAW;
++      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
++      fmt->xfer_func = V4L2_XFER_FUNC_NONE;
++}
++
++static int imx219_init_cfg(struct v4l2_subdev *sd,
++                         struct v4l2_subdev_state *state)
++{
++      struct imx219 *imx219 = to_imx219(sd);
++      struct v4l2_mbus_framefmt *format;
++      struct v4l2_rect *crop;
++
++      /* Initialize the format. */
++      format = v4l2_subdev_get_pad_format(sd, state, 0);
++      imx219_update_pad_format(imx219, &supported_modes[0], format,
++                               MEDIA_BUS_FMT_SRGGB10_1X10);
++
++      /* Initialize the crop rectangle. */
++      crop = v4l2_subdev_get_pad_crop(sd, state, 0);
++      crop->top = IMX219_PIXEL_ARRAY_TOP;
++      crop->left = IMX219_PIXEL_ARRAY_LEFT;
++      crop->width = IMX219_PIXEL_ARRAY_WIDTH;
++      crop->height = IMX219_PIXEL_ARRAY_HEIGHT;
++
++      return 0;
++}
++
++static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
++                               struct v4l2_subdev_state *sd_state,
++                               struct v4l2_subdev_mbus_code_enum *code)
++{
++      struct imx219 *imx219 = to_imx219(sd);
++
++      if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4))
++              return -EINVAL;
++
++      code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]);
++
++      return 0;
++}
++
++static int imx219_enum_frame_size(struct v4l2_subdev *sd,
++                                struct v4l2_subdev_state *sd_state,
++                                struct v4l2_subdev_frame_size_enum *fse)
++{
++      struct imx219 *imx219 = to_imx219(sd);
++      u32 code;
++
++      if (fse->index >= ARRAY_SIZE(supported_modes))
++              return -EINVAL;
++
++      code = imx219_get_format_code(imx219, fse->code);
++      if (fse->code != code)
++              return -EINVAL;
++
++      fse->min_width = supported_modes[fse->index].width;
++      fse->max_width = fse->min_width;
++      fse->min_height = supported_modes[fse->index].height;
++      fse->max_height = fse->min_height;
++
++      return 0;
++}
++
++static int imx219_set_pad_format(struct v4l2_subdev *sd,
++                               struct v4l2_subdev_state *sd_state,
++                               struct v4l2_subdev_format *fmt)
++{
++      struct imx219 *imx219 = to_imx219(sd);
++      const struct imx219_mode *mode;
++      int exposure_max, exposure_def, hblank;
++      struct v4l2_mbus_framefmt *format;
++      struct v4l2_rect *crop;
++
++      mode = v4l2_find_nearest_size(supported_modes,
++                                    ARRAY_SIZE(supported_modes),
++                                    width, height,
++                                    fmt->format.width, fmt->format.height);
++
++      imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code);
++
++      format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
++      crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0);
++
++      *format = fmt->format;
++      *crop = mode->crop;
++
++      if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
++              imx219->mode = mode;
++              /* Update limits and set FPS to default */
++              __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
++                                       IMX219_VTS_MAX - mode->height, 1,
++                                       mode->vts_def - mode->height);
++              __v4l2_ctrl_s_ctrl(imx219->vblank,
++                                 mode->vts_def - mode->height);
++              /* Update max exposure while meeting expected vblanking */
++              exposure_max = mode->vts_def - 4;
++              exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
++                      exposure_max : IMX219_EXPOSURE_DEFAULT;
++              __v4l2_ctrl_modify_range(imx219->exposure,
++                                       imx219->exposure->minimum,
++                                       exposure_max, imx219->exposure->step,
++                                       exposure_def);
++              /*
++               * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank
++               * depends on mode->width only, and is not changeble in any
++               * way other than changing the mode.
++               */
++              hblank = IMX219_PPL_DEFAULT - mode->width;
++              __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1,
++                                       hblank);
++      }
++
++      return 0;
++}
++
++static int imx219_get_selection(struct v4l2_subdev *sd,
++                              struct v4l2_subdev_state *sd_state,
++                              struct v4l2_subdev_selection *sel)
++{
++      switch (sel->target) {
++      case V4L2_SEL_TGT_CROP: {
++              sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0);
++              return 0;
++      }
++
++      case V4L2_SEL_TGT_NATIVE_SIZE:
++              sel->r.top = 0;
++              sel->r.left = 0;
++              sel->r.width = IMX219_NATIVE_WIDTH;
++              sel->r.height = IMX219_NATIVE_HEIGHT;
++
++              return 0;
++
++      case V4L2_SEL_TGT_CROP_DEFAULT:
++      case V4L2_SEL_TGT_CROP_BOUNDS:
++              sel->r.top = IMX219_PIXEL_ARRAY_TOP;
++              sel->r.left = IMX219_PIXEL_ARRAY_LEFT;
++              sel->r.width = IMX219_PIXEL_ARRAY_WIDTH;
++              sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT;
++
++              return 0;
++      }
++
++      return -EINVAL;
++}
++
++static const struct v4l2_subdev_core_ops imx219_core_ops = {
++      .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
++      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
++};
++
++static const struct v4l2_subdev_video_ops imx219_video_ops = {
++      .s_stream = imx219_set_stream,
++};
++
++static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
++      .init_cfg = imx219_init_cfg,
++      .enum_mbus_code = imx219_enum_mbus_code,
++      .get_fmt = v4l2_subdev_get_fmt,
++      .set_fmt = imx219_set_pad_format,
++      .get_selection = imx219_get_selection,
++      .enum_frame_size = imx219_enum_frame_size,
++};
++
++static const struct v4l2_subdev_ops imx219_subdev_ops = {
++      .core = &imx219_core_ops,
++      .video = &imx219_video_ops,
++      .pad = &imx219_pad_ops,
++};
++
++
++/* -----------------------------------------------------------------------------
++ * Power management
++ */
++
+ static int imx219_power_on(struct device *dev)
+ {
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+@@ -987,6 +1149,10 @@ error:
+       return ret;
+ }
++/* -----------------------------------------------------------------------------
++ * Probe & remove
++ */
++
+ static int imx219_get_regulators(struct imx219 *imx219)
+ {
+       struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
+@@ -1023,156 +1189,6 @@ static int imx219_identify_module(struct
+       return 0;
+ }
+-static const struct v4l2_subdev_core_ops imx219_core_ops = {
+-      .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+-      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+-};
+-
+-static const struct v4l2_subdev_video_ops imx219_video_ops = {
+-      .s_stream = imx219_set_stream,
+-};
+-
+-static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
+-      .init_cfg = imx219_init_cfg,
+-      .enum_mbus_code = imx219_enum_mbus_code,
+-      .get_fmt = v4l2_subdev_get_fmt,
+-      .set_fmt = imx219_set_pad_format,
+-      .get_selection = imx219_get_selection,
+-      .enum_frame_size = imx219_enum_frame_size,
+-};
+-
+-static const struct v4l2_subdev_ops imx219_subdev_ops = {
+-      .core = &imx219_core_ops,
+-      .video = &imx219_video_ops,
+-      .pad = &imx219_pad_ops,
+-};
+-
+-
+-static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
+-{
+-      return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE;
+-}
+-
+-/* Initialize control handlers */
+-static int imx219_init_controls(struct imx219 *imx219)
+-{
+-      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
+-      const struct imx219_mode *mode = &supported_modes[0];
+-      struct v4l2_ctrl_handler *ctrl_hdlr;
+-      struct v4l2_fwnode_device_properties props;
+-      int exposure_max, exposure_def, hblank;
+-      int i, ret;
+-
+-      ctrl_hdlr = &imx219->ctrl_handler;
+-      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
+-      if (ret)
+-              return ret;
+-
+-      /* By default, PIXEL_RATE is read only */
+-      imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+-                                             V4L2_CID_PIXEL_RATE,
+-                                             imx219_get_pixel_rate(imx219),
+-                                             imx219_get_pixel_rate(imx219), 1,
+-                                             imx219_get_pixel_rate(imx219));
+-
+-      imx219->link_freq =
+-              v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops,
+-                                     V4L2_CID_LINK_FREQ,
+-                                     ARRAY_SIZE(imx219_link_freq_menu) - 1, 0,
+-                                     (imx219->lanes == 2) ? imx219_link_freq_menu :
+-                                     imx219_link_freq_4lane_menu);
+-      if (imx219->link_freq)
+-              imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+-
+-      /* Initial vblank/hblank/exposure parameters based on current mode */
+-      imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+-                                         V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
+-                                         IMX219_VTS_MAX - mode->height, 1,
+-                                         mode->vts_def - mode->height);
+-      hblank = IMX219_PPL_DEFAULT - mode->width;
+-      imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+-                                         V4L2_CID_HBLANK, hblank, hblank,
+-                                         1, hblank);
+-      if (imx219->hblank)
+-              imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+-      exposure_max = mode->vts_def - 4;
+-      exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
+-              exposure_max : IMX219_EXPOSURE_DEFAULT;
+-      imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+-                                           V4L2_CID_EXPOSURE,
+-                                           IMX219_EXPOSURE_MIN, exposure_max,
+-                                           IMX219_EXPOSURE_STEP,
+-                                           exposure_def);
+-
+-      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+-                        IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX,
+-                        IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT);
+-
+-      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
+-                        IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX,
+-                        IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT);
+-
+-      imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+-                                        V4L2_CID_HFLIP, 0, 1, 1, 0);
+-      if (imx219->hflip)
+-              imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+-
+-      imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+-                                        V4L2_CID_VFLIP, 0, 1, 1, 0);
+-      if (imx219->vflip)
+-              imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+-
+-      v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops,
+-                                   V4L2_CID_TEST_PATTERN,
+-                                   ARRAY_SIZE(imx219_test_pattern_menu) - 1,
+-                                   0, 0, imx219_test_pattern_menu);
+-      for (i = 0; i < 4; i++) {
+-              /*
+-               * The assumption is that
+-               * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1
+-               * V4L2_CID_TEST_PATTERN_BLUE   == V4L2_CID_TEST_PATTERN_RED + 2
+-               * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3
+-               */
+-              v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+-                                V4L2_CID_TEST_PATTERN_RED + i,
+-                                IMX219_TESTP_COLOUR_MIN,
+-                                IMX219_TESTP_COLOUR_MAX,
+-                                IMX219_TESTP_COLOUR_STEP,
+-                                IMX219_TESTP_COLOUR_MAX);
+-              /* The "Solid color" pattern is white by default */
+-      }
+-
+-      if (ctrl_hdlr->error) {
+-              ret = ctrl_hdlr->error;
+-              dev_err(&client->dev, "%s control init failed (%d)\n",
+-                      __func__, ret);
+-              goto error;
+-      }
+-
+-      ret = v4l2_fwnode_device_parse(&client->dev, &props);
+-      if (ret)
+-              goto error;
+-
+-      ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops,
+-                                            &props);
+-      if (ret)
+-              goto error;
+-
+-      imx219->sd.ctrl_handler = ctrl_hdlr;
+-
+-      return 0;
+-
+-error:
+-      v4l2_ctrl_handler_free(ctrl_hdlr);
+-
+-      return ret;
+-}
+-
+-static void imx219_free_controls(struct imx219 *imx219)
+-{
+-      v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
+-}
+-
+ static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
+ {
+       struct fwnode_handle *endpoint;
diff --git a/queue-6.6/media-i2c-imx219-rename-vts-to-frm_length.patch b/queue-6.6/media-i2c-imx219-rename-vts-to-frm_length.patch
new file mode 100644 (file)
index 0000000..641331b
--- /dev/null
@@ -0,0 +1,130 @@
+From stable+bounces-295118-greg=kroah.com@vger.kernel.org Tue Aug  4 13:08:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  4 Aug 2026 06:47:36 -0400
+Subject: media: i2c: imx219: Rename VTS to FRM_LENGTH
+To: stable@vger.kernel.org
+Cc: Jai Luthra <jai.luthra@ideasonboard.com>, Dave Stevenson <dave.stevenson@raspberrypi.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, Hans Verkuil <hverkuil@xs4all.nl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260804104737.2827302-6-sashal@kernel.org>
+
+From: Jai Luthra <jai.luthra@ideasonboard.com>
+
+[ Upstream commit 04f78503f99ae7e9887c7fe5e4bc54a7cfb10fe0 ]
+
+The IMX219 datasheet refers to the vertical length + blanking as
+FRM_LENGTH instead of VTS.
+
+Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/i2c/imx219.c |   31 +++++++++++++++----------------
+ 1 file changed, 15 insertions(+), 16 deletions(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -71,9 +71,8 @@
+ #define IMX219_EXPOSURE_MAX           65535
+ /* V_TIMING internal */
+-#define IMX219_REG_VTS                        CCI_REG16(0x0160)
+-#define IMX219_VTS_MAX                        0xffff
+-
++#define IMX219_REG_FRM_LENGTH_A               CCI_REG16(0x0160)
++#define IMX219_FLL_MAX                        0xffff
+ #define IMX219_VBLANK_MIN             32
+ /* HBLANK control - read only */
+@@ -163,7 +162,7 @@ struct imx219_mode {
+       unsigned int height;
+       /* V-timing */
+-      unsigned int vts_def;
++      unsigned int fll_def;
+       /* Default register values */
+       struct imx219_reg_list reg_list;
+@@ -363,7 +362,7 @@ static const struct imx219_mode supporte
+               /* 8MPix 15fps mode */
+               .width = 3280,
+               .height = 2464,
+-              .vts_def = 3526,
++              .fll_def = 3526,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
+                       .regs = mode_3280x2464_regs,
+@@ -374,7 +373,7 @@ static const struct imx219_mode supporte
+               /* 1080P 30fps cropped */
+               .width = 1920,
+               .height = 1080,
+-              .vts_def = 1763,
++              .fll_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
+                       .regs = mode_1920_1080_regs,
+@@ -385,7 +384,7 @@ static const struct imx219_mode supporte
+               /* 2x2 binned 30fps mode */
+               .width = 1640,
+               .height = 1232,
+-              .vts_def = 1763,
++              .fll_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
+                       .regs = mode_1640_1232_regs,
+@@ -396,7 +395,7 @@ static const struct imx219_mode supporte
+               /* 640x480 30fps mode */
+               .width = 640,
+               .height = 480,
+-              .vts_def = 1763,
++              .fll_def = 1763,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_640_480_regs),
+                       .regs = mode_640_480_regs,
+@@ -518,7 +517,7 @@ static int imx219_set_ctrl(struct v4l2_c
+                         imx219->hflip->val | imx219->vflip->val << 1, &ret);
+               break;
+       case V4L2_CID_VBLANK:
+-              cci_write(imx219->regmap, IMX219_REG_VTS,
++              cci_write(imx219->regmap, IMX219_REG_FRM_LENGTH_A,
+                         format->height + ctrl->val, &ret);
+               break;
+       case V4L2_CID_TEST_PATTERN_RED:
+@@ -593,15 +592,15 @@ static int imx219_init_controls(struct i
+       /* Initial vblank/hblank/exposure parameters based on current mode */
+       imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+                                          V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
+-                                         IMX219_VTS_MAX - mode->height, 1,
+-                                         mode->vts_def - mode->height);
++                                         IMX219_FLL_MAX - mode->height, 1,
++                                         mode->fll_def - mode->height);
+       hblank = IMX219_PPL_DEFAULT - mode->width;
+       imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+                                          V4L2_CID_HBLANK, hblank, hblank,
+                                          1, hblank);
+       if (imx219->hblank)
+               imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+-      exposure_max = mode->vts_def - 4;
++      exposure_max = mode->fll_def - 4;
+       exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
+               exposure_max : IMX219_EXPOSURE_DEFAULT;
+       imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+@@ -969,12 +968,12 @@ static int imx219_set_pad_format(struct
+               imx219->mode = mode;
+               /* Update limits and set FPS to default */
+               __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
+-                                       IMX219_VTS_MAX - mode->height, 1,
+-                                       mode->vts_def - mode->height);
++                                       IMX219_FLL_MAX - mode->height, 1,
++                                       mode->fll_def - mode->height);
+               __v4l2_ctrl_s_ctrl(imx219->vblank,
+-                                 mode->vts_def - mode->height);
++                                 mode->fll_def - mode->height);
+               /* Update max exposure while meeting expected vblanking */
+-              exposure_max = mode->vts_def - 4;
++              exposure_max = mode->fll_def - 4;
+               exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
+                       exposure_max : IMX219_EXPOSURE_DEFAULT;
+               __v4l2_ctrl_modify_range(imx219->exposure,
diff --git a/queue-6.6/media-imx219-fix-maximum-frame-length-in-lines.patch b/queue-6.6/media-imx219-fix-maximum-frame-length-in-lines.patch
new file mode 100644 (file)
index 0000000..e900322
--- /dev/null
@@ -0,0 +1,37 @@
+From stable+bounces-295120-greg=kroah.com@vger.kernel.org Tue Aug  4 12:57:41 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  4 Aug 2026 06:47:37 -0400
+Subject: media: imx219: Fix maximum frame length in lines
+To: stable@vger.kernel.org
+Cc: Sakari Ailus <sakari.ailus@linux.intel.com>, Dave Stevenson <dave.stevenson@raspberrypi.com>, Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260804104737.2827302-7-sashal@kernel.org>
+
+From: Sakari Ailus <sakari.ailus@linux.intel.com>
+
+[ Upstream commit 2c4f1ba7354312ad2d6e34e70a518a51a9344715 ]
+
+The driver used the maximum frame length in lines value of 0xffff, but the
+maximum appears to be 0xfffe instead. Fix it.
+
+Fixes: 1283b3b8f82b ("media: i2c: Add driver for Sony IMX219 sensor")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/i2c/imx219.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -72,7 +72,7 @@
+ /* V_TIMING internal */
+ #define IMX219_REG_FRM_LENGTH_A               CCI_REG16(0x0160)
+-#define IMX219_FLL_MAX                        0xffff
++#define IMX219_FLL_MAX                        0xfffe
+ #define IMX219_VBLANK_MIN             32
+ /* HBLANK control - read only */
diff --git a/queue-6.6/media-v4l-async-set-owner-for-async-sub-devices.patch b/queue-6.6/media-v4l-async-set-owner-for-async-sub-devices.patch
new file mode 100644 (file)
index 0000000..db1ad4a
--- /dev/null
@@ -0,0 +1,71 @@
+From stable+bounces-296825-greg=kroah.com@vger.kernel.org Thu Aug  6 15:38:06 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 09:36:14 -0400
+Subject: media: v4l: async: Set owner for async sub-devices
+To: stable@vger.kernel.org
+Cc: Sakari Ailus <sakari.ailus@linux.intel.com>, Mauro Carvalho Chehab <mchehab@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260806133615.470300-1-sashal@kernel.org>
+
+From: Sakari Ailus <sakari.ailus@linux.intel.com>
+
+[ Upstream commit 8a718752f5c339137c5b05e54f116cd26d5a4143 ]
+
+Set the owner field of the async sub-devices by making
+v4l2_async_register_subdev() a macro and obtaining THIS_MODULE that way.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Stable-dep-of: 06cb687a5132 ("media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-async.c |    8 ++++++--
+ include/media/v4l2-async.h           |    4 +++-
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-async.c
++++ b/drivers/media/v4l2-core/v4l2-async.c
+@@ -798,7 +798,7 @@ v4l2_async_connection_unique(struct v4l2
+ }
+ EXPORT_SYMBOL_GPL(v4l2_async_connection_unique);
+-int v4l2_async_register_subdev(struct v4l2_subdev *sd)
++int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module)
+ {
+       struct v4l2_async_notifier *subdev_notifier;
+       struct v4l2_async_notifier *notifier;
+@@ -822,6 +822,8 @@ int v4l2_async_register_subdev(struct v4
+               return -EINVAL;
+       }
++      sd->owner = module;
++
+       mutex_lock(&list_lock);
+       list_for_each_entry(notifier, &notifier_list, notifier_entry) {
+@@ -869,9 +871,11 @@ err_unbind_one:
+ err_unlock:
+       mutex_unlock(&list_lock);
++      sd->owner = NULL;
++
+       return ret;
+ }
+-EXPORT_SYMBOL(v4l2_async_register_subdev);
++EXPORT_SYMBOL(__v4l2_async_register_subdev);
+ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
+ {
+--- a/include/media/v4l2-async.h
++++ b/include/media/v4l2-async.h
+@@ -310,7 +310,9 @@ void v4l2_async_nf_cleanup(struct v4l2_a
+  *
+  * @sd: pointer to &struct v4l2_subdev
+  */
+-int v4l2_async_register_subdev(struct v4l2_subdev *sd);
++#define v4l2_async_register_subdev(sd) \
++      __v4l2_async_register_subdev(sd, THIS_MODULE)
++int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module);
+ /**
+  * v4l2_async_register_subdev_sensor - registers a sensor sub-device to the
diff --git a/queue-6.6/media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch b/queue-6.6/media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch
new file mode 100644 (file)
index 0000000..ee6d5d8
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-296826-greg=kroah.com@vger.kernel.org Thu Aug  6 15:45:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 09:36:15 -0400
+Subject: media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()
+To: stable@vger.kernel.org
+Cc: Mirela Rabulea <mirela.rabulea@nxp.com>, Frank Li <Frank.Li@nxp.com>, Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260806133615.470300-2-sashal@kernel.org>
+
+From: Mirela Rabulea <mirela.rabulea@nxp.com>
+
+[ Upstream commit 06cb687a5132fcffe624c0070576ab852ac6b568 ]
+
+The v4l2 helper v4l2_async_register_subdev_sensor() calls
+v4l2_async_register_subdev(), which is a macro that expands to
+__v4l2_async_register_subdev(sd,THIS_MODULE). Since the macro is expanded
+inside v4l2-fwnode.c, THIS_MODULE resolves to the v4l2-fwnode module
+rather than the sensor driver module that originally set sd->owner. When
+v4l2-fwnode is built-in, THIS_MODULE evaluates to NULL, which then
+overwrites the sensor driver's owner with NULL.
+
+This causes the problem that the sensor module's reference count is never
+incremented during async registration, so the module can be removed while
+the subdevice is still in use by a notifier (e.g., a CSI-2 receiver
+bridge driver).
+
+Fix this by renaming v4l2_async_register_subdev_sensor() to
+__v4l2_async_register_subdev_sensor() with an added explicit module
+argument and introducing a wrapper macro:
+    #define v4l2_async_register_subdev_sensor(sd) \
+        __v4l2_async_register_subdev_sensor(sd, THIS_MODULE)
+
+This ensures the sensor driver module is properly referenced even when
+the sensor driver does not init the owner field before calling
+v4l2_async_register_subdev_sensor() and prevents premature module removal.
+
+Fixes: aef69d54755d ("media: v4l: fwnode: Add a convenience function for registering sensors")
+Cc: stable@vger.kernel.org
+Suggested-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/linux-media/20240315073125.275501-2-sakari.ailus@linux.intel.com/
+Signed-off-by: Mirela Rabulea <mirela.rabulea@nxp.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-fwnode.c |    6 +++---
+ include/media/v4l2-async.h            |    4 +++-
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-fwnode.c
++++ b/drivers/media/v4l2-core/v4l2-fwnode.c
+@@ -1203,7 +1203,7 @@ v4l2_async_nf_parse_fwnode_sensor(struct
+       return 0;
+ }
+-int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
++int __v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd, struct module *module)
+ {
+       struct v4l2_async_notifier *notifier;
+       int ret;
+@@ -1229,7 +1229,7 @@ int v4l2_async_register_subdev_sensor(st
+       if (ret < 0)
+               goto out_cleanup;
+-      ret = v4l2_async_register_subdev(sd);
++      ret = __v4l2_async_register_subdev(sd, module);
+       if (ret < 0)
+               goto out_unregister;
+@@ -1247,7 +1247,7 @@ out_cleanup:
+       return ret;
+ }
+-EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor);
++EXPORT_SYMBOL_GPL(__v4l2_async_register_subdev_sensor);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
+--- a/include/media/v4l2-async.h
++++ b/include/media/v4l2-async.h
+@@ -333,8 +333,10 @@ int __v4l2_async_register_subdev(struct
+  * An error is returned if the module is no longer loaded on any attempts
+  * to register it.
+  */
++#define v4l2_async_register_subdev_sensor(sd) \
++      __v4l2_async_register_subdev_sensor(sd, THIS_MODULE)
+ int __must_check
+-v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd);
++__v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd, struct module *module);
+ /**
+  * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
diff --git a/queue-6.6/mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch b/queue-6.6/mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch
new file mode 100644 (file)
index 0000000..4d1f99a
--- /dev/null
@@ -0,0 +1,155 @@
+From stable+bounces-297278-greg=kroah.com@vger.kernel.org Fri Aug  7 13:55:47 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  7 Aug 2026 07:48:11 -0400
+Subject: mptcp: add mptcp_userspace_pm_lookup_addr helper
+To: stable@vger.kernel.org
+Cc: Geliang Tang <tanggeliang@kylinos.cn>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807114813.2056374-2-sashal@kernel.org>
+
+From: Geliang Tang <tanggeliang@kylinos.cn>
+
+[ Upstream commit e7b4083b90b7213902124d13fd1ed808360e32b1 ]
+
+Like __lookup_addr() helper in pm_netlink.c, a new helper
+mptcp_userspace_pm_lookup_addr() is also defined in pm_userspace.c.
+It looks up the corresponding mptcp_pm_addr_entry address in
+userspace_pm_local_addr_list through the passed "addr" parameter
+and returns the found address entry.
+
+This helper can be used in mptcp_userspace_pm_delete_local_addr(),
+mptcp_userspace_pm_set_flags(), mptcp_userspace_pm_get_local_id()
+and mptcp_userspace_pm_is_backup() to simplify the code.
+
+Please note that with this change now list_for_each_entry() is used in
+mptcp_userspace_pm_append_new_local_addr(), not list_for_each_entry_safe(),
+but that's OK to do so because mptcp_userspace_pm_lookup_addr() only
+returns an entry from the list, the list hasn't been modified here.
+
+Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
+Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20241213-net-next-mptcp-pm-misc-cleanup-v1-1-ddb6d00109a8@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 9bc6d5e4ca9f ("mptcp: pm: userspace: fix use-after-free in get_local_id")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/pm_userspace.c |   71 +++++++++++++++++++++++------------------------
+ 1 file changed, 36 insertions(+), 35 deletions(-)
+
+--- a/net/mptcp/pm_userspace.c
++++ b/net/mptcp/pm_userspace.c
+@@ -25,6 +25,19 @@ void mptcp_free_local_addr_list(struct m
+       }
+ }
++static struct mptcp_pm_addr_entry *
++mptcp_userspace_pm_lookup_addr(struct mptcp_sock *msk,
++                             const struct mptcp_addr_info *addr)
++{
++      struct mptcp_pm_addr_entry *entry;
++
++      list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
++              if (mptcp_addresses_equal(&entry->addr, addr, false))
++                      return entry;
++      }
++      return NULL;
++}
++
+ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
+                                                   struct mptcp_pm_addr_entry *entry,
+                                                   bool needs_id)
+@@ -89,22 +102,20 @@ append_err:
+ static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk,
+                                               struct mptcp_pm_addr_entry *addr)
+ {
+-      struct mptcp_pm_addr_entry *entry, *tmp;
+       struct sock *sk = (struct sock *)msk;
++      struct mptcp_pm_addr_entry *entry;
+-      list_for_each_entry_safe(entry, tmp, &msk->pm.userspace_pm_local_addr_list, list) {
+-              if (mptcp_addresses_equal(&entry->addr, &addr->addr, false)) {
+-                      /* TODO: a refcount is needed because the entry can
+-                       * be used multiple times (e.g. fullmesh mode).
+-                       */
+-                      list_del_rcu(&entry->list);
+-                      sock_kfree_s(sk, entry, sizeof(*entry));
+-                      msk->pm.local_addr_used--;
+-                      return 0;
+-              }
+-      }
+-
+-      return -EINVAL;
++      entry = mptcp_userspace_pm_lookup_addr(msk, &addr->addr);
++      if (!entry)
++              return -EINVAL;
++
++      /* TODO: a refcount is needed because the entry can
++       * be used multiple times (e.g. fullmesh mode).
++       */
++      list_del_rcu(&entry->list);
++      sock_kfree_s(sk, entry, sizeof(*entry));
++      msk->pm.local_addr_used--;
++      return 0;
+ }
+ static struct mptcp_pm_addr_entry *
+@@ -139,17 +150,12 @@ int mptcp_userspace_pm_get_flags_and_ifi
+ int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
+                                   struct mptcp_addr_info *skc)
+ {
+-      struct mptcp_pm_addr_entry *entry = NULL, *e, new_entry;
++      struct mptcp_pm_addr_entry *entry = NULL, new_entry;
+       __be16 msk_sport =  ((struct inet_sock *)
+                            inet_sk((struct sock *)msk))->inet_sport;
+       spin_lock_bh(&msk->pm.lock);
+-      list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) {
+-              if (mptcp_addresses_equal(&e->addr, skc, false)) {
+-                      entry = e;
+-                      break;
+-              }
+-      }
++      entry = mptcp_userspace_pm_lookup_addr(msk, skc);
+       spin_unlock_bh(&msk->pm.lock);
+       if (entry)
+               return entry->addr.id;
+@@ -169,15 +175,11 @@ bool mptcp_userspace_pm_is_backup(struct
+                                 struct mptcp_addr_info *skc)
+ {
+       struct mptcp_pm_addr_entry *entry;
+-      bool backup = false;
++      bool backup;
+       spin_lock_bh(&msk->pm.lock);
+-      list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
+-              if (mptcp_addresses_equal(&entry->addr, skc, false)) {
+-                      backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
+-                      break;
+-              }
+-      }
++      entry = mptcp_userspace_pm_lookup_addr(msk, skc);
++      backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
+       spin_unlock_bh(&msk->pm.lock);
+       return backup;
+@@ -591,13 +593,12 @@ int mptcp_userspace_pm_set_flags(struct
+               goto set_flags_err;
+       spin_lock_bh(&msk->pm.lock);
+-      list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
+-              if (mptcp_addresses_equal(&entry->addr, &loc->addr, false)) {
+-                      if (bkup)
+-                              entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
+-                      else
+-                              entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
+-              }
++      entry = mptcp_userspace_pm_lookup_addr(msk, &loc->addr);
++      if (entry) {
++              if (bkup)
++                      entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
++              else
++                      entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
+       }
+       spin_unlock_bh(&msk->pm.lock);
diff --git a/queue-6.6/mptcp-pm-avoid-code-duplication-to-lookup-endp.patch b/queue-6.6/mptcp-pm-avoid-code-duplication-to-lookup-endp.patch
new file mode 100644 (file)
index 0000000..5925eb7
--- /dev/null
@@ -0,0 +1,71 @@
+From stable+bounces-297279-greg=kroah.com@vger.kernel.org Fri Aug  7 13:55:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  7 Aug 2026 07:48:10 -0400
+Subject: mptcp: pm: avoid code duplication to lookup endp
+To: stable@vger.kernel.org
+Cc: Geliang Tang <tanggeliang@kylinos.cn>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807114813.2056374-1-sashal@kernel.org>
+
+From: Geliang Tang <tanggeliang@kylinos.cn>
+
+[ Upstream commit 1d7fa6ceb91fddbe38cae3521d5d1075bce6a00e ]
+
+The helper __lookup_addr() can be used in mptcp_pm_nl_get_local_id()
+and mptcp_pm_nl_is_backup() to simplify the code, and avoid code
+duplication.
+
+Co-developed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20241115-net-next-mptcp-pm-lockless-dump-v1-2-f4a1bcb4ca2c@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 9bc6d5e4ca9f ("mptcp: pm: userspace: fix use-after-free in get_local_id")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/pm_netlink.c |   20 ++++++--------------
+ 1 file changed, 6 insertions(+), 14 deletions(-)
+
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1281,17 +1281,13 @@ int mptcp_pm_nl_get_local_id(struct mptc
+ {
+       struct mptcp_pm_addr_entry *entry;
+       struct pm_nl_pernet *pernet;
+-      int ret = -1;
++      int ret;
+       pernet = pm_nl_get_pernet_from_msk(msk);
+       rcu_read_lock();
+-      list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
+-              if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) {
+-                      ret = entry->addr.id;
+-                      break;
+-              }
+-      }
++      entry = __lookup_addr(pernet, skc);
++      ret = entry ? entry->addr.id : -1;
+       rcu_read_unlock();
+       if (ret >= 0)
+               return ret;
+@@ -1318,15 +1314,11 @@ bool mptcp_pm_nl_is_backup(struct mptcp_
+ {
+       struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk);
+       struct mptcp_pm_addr_entry *entry;
+-      bool backup = false;
++      bool backup;
+       rcu_read_lock();
+-      list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
+-              if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) {
+-                      backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
+-                      break;
+-              }
+-      }
++      entry = __lookup_addr(pernet, skc);
++      backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
+       rcu_read_unlock();
+       return backup;
diff --git a/queue-6.6/mptcp-pm-use-addr-entry-for-get_local_id.patch b/queue-6.6/mptcp-pm-use-addr-entry-for-get_local_id.patch
new file mode 100644 (file)
index 0000000..d533b15
--- /dev/null
@@ -0,0 +1,155 @@
+From stable+bounces-297281-greg=kroah.com@vger.kernel.org Fri Aug  7 13:51:26 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  7 Aug 2026 07:48:12 -0400
+Subject: mptcp: pm: use addr entry for get_local_id
+To: stable@vger.kernel.org
+Cc: Geliang Tang <tanggeliang@kylinos.cn>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807114813.2056374-3-sashal@kernel.org>
+
+From: Geliang Tang <tanggeliang@kylinos.cn>
+
+[ Upstream commit 7462fe22cc74321eb663768848976d42eba3ddbb ]
+
+The following code in mptcp_userspace_pm_get_local_id() that assigns "skc"
+to "new_entry" is not allowed in BPF if we use the same code to implement
+the get_local_id() interface of a BFP path manager:
+
+       memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry));
+       new_entry.addr = *skc;
+       new_entry.addr.id = 0;
+       new_entry.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
+
+To solve the issue, this patch moves this assignment to "new_entry" forward
+to mptcp_pm_get_local_id(), and then passing "new_entry" as a parameter to
+both mptcp_pm_nl_get_local_id() and mptcp_userspace_pm_get_local_id().
+
+No behavioural changes intended.
+
+Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
+Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20250307-net-next-mptcp-pm-reorg-v1-1-abef20ada03b@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 9bc6d5e4ca9f ("mptcp: pm: userspace: fix use-after-free in get_local_id")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/pm.c           |    9 ++++++---
+ net/mptcp/pm_netlink.c   |   11 ++++-------
+ net/mptcp/pm_userspace.c |   17 ++++++-----------
+ net/mptcp/protocol.h     |    6 ++++--
+ 4 files changed, 20 insertions(+), 23 deletions(-)
+
+--- a/net/mptcp/pm.c
++++ b/net/mptcp/pm.c
+@@ -428,7 +428,7 @@ out_unlock:
+ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
+ {
+-      struct mptcp_addr_info skc_local;
++      struct mptcp_pm_addr_entry skc_local = { 0 };
+       struct mptcp_addr_info msk_local;
+       if (WARN_ON_ONCE(!msk))
+@@ -438,10 +438,13 @@ int mptcp_pm_get_local_id(struct mptcp_s
+        * addr
+        */
+       mptcp_local_address((struct sock_common *)msk, &msk_local);
+-      mptcp_local_address((struct sock_common *)skc, &skc_local);
+-      if (mptcp_addresses_equal(&msk_local, &skc_local, false))
++      mptcp_local_address((struct sock_common *)skc, &skc_local.addr);
++      if (mptcp_addresses_equal(&msk_local, &skc_local.addr, false))
+               return 0;
++      skc_local.addr.id = 0;
++      skc_local.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
++
+       if (mptcp_pm_is_userspace(msk))
+               return mptcp_userspace_pm_get_local_id(msk, &skc_local);
+       return mptcp_pm_nl_get_local_id(msk, &skc_local);
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1277,7 +1277,8 @@ static int mptcp_pm_nl_create_listen_soc
+       return err;
+ }
+-int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc)
++int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk,
++                           struct mptcp_pm_addr_entry *skc)
+ {
+       struct mptcp_pm_addr_entry *entry;
+       struct pm_nl_pernet *pernet;
+@@ -1286,7 +1287,7 @@ int mptcp_pm_nl_get_local_id(struct mptc
+       pernet = pm_nl_get_pernet_from_msk(msk);
+       rcu_read_lock();
+-      entry = __lookup_addr(pernet, skc);
++      entry = __lookup_addr(pernet, &skc->addr);
+       ret = entry ? entry->addr.id : -1;
+       rcu_read_unlock();
+       if (ret >= 0)
+@@ -1297,12 +1298,8 @@ int mptcp_pm_nl_get_local_id(struct mptc
+       if (!entry)
+               return -ENOMEM;
+-      entry->addr = *skc;
+-      entry->addr.id = 0;
++      *entry = *skc;
+       entry->addr.port = 0;
+-      entry->ifindex = 0;
+-      entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
+-      entry->lsk = NULL;
+       ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, false);
+       if (ret < 0)
+               kfree(entry);
+--- a/net/mptcp/pm_userspace.c
++++ b/net/mptcp/pm_userspace.c
+@@ -148,27 +148,22 @@ int mptcp_userspace_pm_get_flags_and_ifi
+ }
+ int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
+-                                  struct mptcp_addr_info *skc)
++                                  struct mptcp_pm_addr_entry *skc)
+ {
+-      struct mptcp_pm_addr_entry *entry = NULL, new_entry;
+       __be16 msk_sport =  ((struct inet_sock *)
+                            inet_sk((struct sock *)msk))->inet_sport;
++      struct mptcp_pm_addr_entry *entry;
+       spin_lock_bh(&msk->pm.lock);
+-      entry = mptcp_userspace_pm_lookup_addr(msk, skc);
++      entry = mptcp_userspace_pm_lookup_addr(msk, &skc->addr);
+       spin_unlock_bh(&msk->pm.lock);
+       if (entry)
+               return entry->addr.id;
+-      memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry));
+-      new_entry.addr = *skc;
+-      new_entry.addr.id = 0;
+-      new_entry.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
++      if (skc->addr.port == msk_sport)
++              skc->addr.port = 0;
+-      if (new_entry.addr.port == msk_sport)
+-              new_entry.addr.port = 0;
+-
+-      return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true);
++      return mptcp_userspace_pm_append_new_local_addr(msk, skc, true);
+ }
+ bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk,
+--- a/net/mptcp/protocol.h
++++ b/net/mptcp/protocol.h
+@@ -1048,8 +1048,10 @@ bool mptcp_pm_add_addr_signal(struct mpt
+ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
+                            struct mptcp_rm_list *rm_list);
+ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
+-int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
+-int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
++int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk,
++                           struct mptcp_pm_addr_entry *skc);
++int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
++                                  struct mptcp_pm_addr_entry *skc);
+ bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc);
+ bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
+ bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
diff --git a/queue-6.6/mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch b/queue-6.6/mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch
new file mode 100644 (file)
index 0000000..c477084
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-297282-greg=kroah.com@vger.kernel.org Fri Aug  7 13:58:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  7 Aug 2026 07:48:13 -0400
+Subject: mptcp: pm: userspace: fix use-after-free in get_local_id
+To: stable@vger.kernel.org
+Cc: Geliang Tang <tanggeliang@kylinos.cn>, Xuanqiang Luo <luoxuanqiang@kylinos.cn>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807114813.2056374-4-sashal@kernel.org>
+
+From: Geliang Tang <tanggeliang@kylinos.cn>
+
+[ Upstream commit 9bc6d5e4ca9f3cbb41d43400b3a31cb0403796c9 ]
+
+In mptcp_pm_userspace_get_local_id(), the address entry is looked up under
+spinlock, but its id is read after dropping the lock. A concurrent deletion
+can free the entry between the unlock and the read, leading to UAF.
+
+The race window is narrow. It was reproduced only with a locally
+constructed stress test that repeatedly overlaps an MP_JOIN SYN with a
+MPTCP_PM_CMD_SUBFLOW_DESTROY request.
+
+However, the KASAN report below confirms that the race is reachable:
+
+  [  666.319376] BUG: KASAN: slab-use-after-free in mptcp_userspace_pm_get_local_id+0x1dc/0x1f0
+  [  666.319386] Read of size 1 at addr ffff888124845610 by task swapper/0/0
+  ...
+  [  666.319401] Call Trace:
+  [  666.319405]  <IRQ>
+  [  666.319408]  dump_stack_lvl+0x53/0x70
+  [  666.319412]  print_address_description.constprop.0+0x2c/0x3b0
+  [  666.319418]  print_report+0xbe/0x2b0
+  [  666.319421]  ? mptcp_userspace_pm_get_local_id+0x1dc/0x1f0
+  [  666.319423]  kasan_report+0xce/0x100
+  [  666.319426]  ? mptcp_userspace_pm_get_local_id+0x1dc/0x1f0
+  [  666.319429]  mptcp_userspace_pm_get_local_id+0x1dc/0x1f0
+  [  666.319433]  mptcp_pm_get_local_id+0x371/0x440
+  ...
+  [  666.319821] Allocated by task 45539:
+  [  666.319844]  kasan_save_stack+0x33/0x60
+  [  666.319855]  kasan_save_track+0x14/0x30
+  [  666.319858]  __kasan_kmalloc+0x8f/0xa0
+  [  666.319863]  __kmalloc_noprof+0x1e7/0x520
+  [  666.319867]  sock_kmalloc+0xdf/0x130
+  [  666.319885]  sock_kmemdup+0x1b/0x40
+  [  666.319888]  mptcp_userspace_pm_append_new_local_addr+0x261/0x500
+  [  666.319910]  mptcp_pm_nl_announce_doit+0x16a/0x610
+  ...
+  [  666.319967] Freed by task 45560:
+  [  666.319988]  kasan_save_stack+0x33/0x60
+  [  666.319991]  kasan_save_track+0x14/0x30
+  [  666.319994]  kasan_save_free_info+0x3b/0x60
+  [  666.319998]  __kasan_slab_free+0x43/0x70
+  [  666.320000]  kfree+0x166/0x440
+  [  666.320003]  sock_kfree_s+0x1d/0x50
+  [  666.320007]  mptcp_userspace_pm_delete_local_addr.isra.0+0x157/0x200
+  [  666.320011]  mptcp_pm_nl_subflow_destroy_doit+0x51d/0xea0
+
+Fix by copying the id into a local variable while still holding the lock,
+and use -1 as a "not found" sentinel.
+
+Fixes: f012d796a6de ("mptcp: check addrs list in userspace_pm_get_local_id")
+Cc: stable@vger.kernel.org
+Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
+Tested-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
+Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20260722-net-mptcp-misc-fixes-7-2-rc5-v1-2-6fb595bc86ef@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/pm_userspace.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/net/mptcp/pm_userspace.c
++++ b/net/mptcp/pm_userspace.c
+@@ -153,12 +153,15 @@ int mptcp_userspace_pm_get_local_id(stru
+       __be16 msk_sport =  ((struct inet_sock *)
+                            inet_sk((struct sock *)msk))->inet_sport;
+       struct mptcp_pm_addr_entry *entry;
++      int id;
+       spin_lock_bh(&msk->pm.lock);
+       entry = mptcp_userspace_pm_lookup_addr(msk, &skc->addr);
++      id = entry ? entry->addr.id : -1;
+       spin_unlock_bh(&msk->pm.lock);
+-      if (entry)
+-              return entry->addr.id;
++
++      if (id != -1)
++              return id;
+       if (skc->addr.port == msk_sport)
+               skc->addr.port = 0;
diff --git a/queue-6.6/netfilter-nf_tables-clone-set-on-flush-only.patch b/queue-6.6/netfilter-nf_tables-clone-set-on-flush-only.patch
new file mode 100644 (file)
index 0000000..227e5c0
--- /dev/null
@@ -0,0 +1,136 @@
+From stable+bounces-296811-greg=kroah.com@vger.kernel.org Thu Aug  6 15:13:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 09:06:52 -0400
+Subject: netfilter: nf_tables: clone set on flush only
+To: stable@vger.kernel.org
+Cc: Pablo Neira Ayuso <pablo@netfilter.org>, syzbot+4924a0edc148e8b4b342@syzkaller.appspotmail.com, Florian Westphal <fw@strlen.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260806130652.335098-1-sashal@kernel.org>
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit fb7fb4016300ac622c964069e286dc83166a5d52 ]
+
+Syzbot with fault injection triggered a failing memory allocation with
+GFP_KERNEL which results in a WARN splat:
+
+iter.err
+WARNING: net/netfilter/nf_tables_api.c:845 at nft_map_deactivate+0x34e/0x3c0 net/netfilter/nf_tables_api.c:845, CPU#0: syz.0.17/5992
+Modules linked in:
+CPU: 0 UID: 0 PID: 5992 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026
+RIP: 0010:nft_map_deactivate+0x34e/0x3c0 net/netfilter/nf_tables_api.c:845
+Code: 8b 05 86 5a 4e 09 48 3b 84 24 a0 00 00 00 75 62 48 8d 65 d8 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc cc e8 63 6d fa f7 90 <0f> 0b 90 43
++80 7c 35 00 00 0f 85 23 fe ff ff e9 26 fe ff ff 89 d9
+RSP: 0018:ffffc900045af780 EFLAGS: 00010293
+RAX: ffffffff89ca45bd RBX: 00000000fffffff4 RCX: ffff888028111e40
+RDX: 0000000000000000 RSI: 00000000fffffff4 RDI: 0000000000000000
+RBP: ffffc900045af870 R08: 0000000000400dc0 R09: 00000000ffffffff
+R10: dffffc0000000000 R11: fffffbfff1d141db R12: ffffc900045af7e0
+R13: 1ffff920008b5f24 R14: dffffc0000000000 R15: ffffc900045af920
+FS:  000055557a6a5500(0000) GS:ffff888125496000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007fb5ea271fc0 CR3: 000000003269e000 CR4: 00000000003526f0
+Call Trace:
+ <TASK>
+ __nft_release_table+0xceb/0x11f0 net/netfilter/nf_tables_api.c:12115
+ nft_rcv_nl_event+0xc25/0xdb0 net/netfilter/nf_tables_api.c:12187
+ notifier_call_chain+0x19d/0x3a0 kernel/notifier.c:85
+ blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380
+ netlink_release+0x123b/0x1ad0 net/netlink/af_netlink.c:761
+ __sock_release net/socket.c:662 [inline]
+ sock_close+0xc3/0x240 net/socket.c:1455
+
+Restrict set clone to the flush set command in the preparation phase.
+Add NFT_ITER_UPDATE_CLONE and use it for this purpose, update the rbtree
+and pipapo backends to only clone the set when this iteration type is
+used.
+
+As for the existing NFT_ITER_UPDATE type, update the pipapo backend to
+use the existing set clone if available, otherwise use the existing set
+representation. After this update, there is no need to clone a set that
+is being deleted, this includes bound anonymous set.
+
+An alternative approach to NFT_ITER_UPDATE_CLONE is to add a .clone
+interface and call it from the flush set path.
+
+Reported-by: syzbot+4924a0edc148e8b4b342@syzkaller.appspotmail.com
+Fixes: 3f1d886cc7c3 ("netfilter: nft_set_pipapo: move cloning of match info to insert/removal path")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/netfilter/nf_tables.h |    2 ++
+ net/netfilter/nf_tables_api.c     |   10 +++++++++-
+ net/netfilter/nft_set_pipapo.c    |   11 +++++++++--
+ 3 files changed, 20 insertions(+), 3 deletions(-)
+
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -302,11 +302,13 @@ struct nft_set_elem {
+  *
+  * @NFT_ITER_READ: read-only iteration over set elements
+  * @NFT_ITER_UPDATE: iteration under mutex to update set element state
++ * @NFT_ITER_UPDATE_CLONE: clone set before iteration under mutex to update element
+  */
+ enum nft_iter_type {
+       NFT_ITER_UNSPEC,
+       NFT_ITER_READ,
+       NFT_ITER_UPDATE,
++      NFT_ITER_UPDATE_CLONE,
+ };
+ struct nft_set;
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -655,6 +655,11 @@ static void nft_map_catchall_deactivate(
+       }
+ }
++/* Use NFT_ITER_UPDATE iterator even if this may be called from the preparation
++ * phase, the set clone might already exist from a previous command, or it might
++ * be a set that is going away and does not require a clone. The netns and
++ * netlink release paths also need to work on the live set.
++ */
+ static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
+ {
+       struct nft_set_iter iter = {
+@@ -7396,9 +7401,12 @@ static int nft_set_catchall_flush(const
+ static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask)
+ {
++      /* The set backend might need to clone the set, do it now from the
++       * preparation phase, use NFT_ITER_UPDATE_CLONE iterator type.
++       */
+       struct nft_set_iter iter = {
+               .genmask        = genmask,
+-              .type           = NFT_ITER_UPDATE,
++              .type           = NFT_ITER_UPDATE_CLONE,
+               .fn             = nft_setelem_flush,
+       };
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -2199,13 +2199,20 @@ static void nft_pipapo_walk(const struct
+       const struct nft_pipapo_match *m;
+       switch (iter->type) {
+-      case NFT_ITER_UPDATE:
++      case NFT_ITER_UPDATE_CLONE:
+               m = pipapo_maybe_clone(set);
+               if (!m) {
+                       iter->err = -ENOMEM;
+                       return;
+               }
+-
++              nft_pipapo_do_walk(ctx, set, m, iter);
++              break;
++      case NFT_ITER_UPDATE:
++              if (priv->clone)
++                      m = priv->clone;
++              else
++                      m = rcu_dereference_protected(priv->match,
++                                                    nft_pipapo_transaction_mutex_held(set));
+               nft_pipapo_do_walk(ctx, set, m, iter);
+               break;
+       case NFT_ITER_READ:
diff --git a/queue-6.6/rxrpc-fix-irq-disabled-in-local_bh_enable.patch b/queue-6.6/rxrpc-fix-irq-disabled-in-local_bh_enable.patch
new file mode 100644 (file)
index 0000000..31f98fa
--- /dev/null
@@ -0,0 +1,148 @@
+From stable+bounces-296804-greg=kroah.com@vger.kernel.org Thu Aug  6 14:49:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 08:46:13 -0400
+Subject: rxrpc: Fix irq-disabled in local_bh_enable()
+To: stable@vger.kernel.org
+Cc: David Howells <dhowells@redhat.com>, Jeffrey Altman <jaltman@auristor.com>, Marc Dionne <marc.dionne@auristor.com>, "Junvyyang, Tencent Zhuque Lab" <zhuque@tencent.com>, LePremierHomme <kwqcheii@proton.me>, Simon Horman <horms@kernel.org>, linux-afs@lists.infradead.org, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260806124613.299390-1-sashal@kernel.org>
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit e4d2878369d590bf8455e3678a644e503172eafa ]
+
+The rxrpc_assess_MTU_size() function calls down into the IP layer to find
+out the MTU size for a route.  When accepting an incoming call, this is
+called from rxrpc_new_incoming_call() which holds interrupts disabled
+across the code that calls down to it.  Unfortunately, the IP layer uses
+local_bh_enable() which, config dependent, throws a warning if IRQs are
+enabled:
+
+WARNING: CPU: 1 PID: 5544 at kernel/softirq.c:387 __local_bh_enable_ip+0x43/0xd0
+...
+RIP: 0010:__local_bh_enable_ip+0x43/0xd0
+...
+Call Trace:
+ <TASK>
+ rt_cache_route+0x7e/0xa0
+ rt_set_nexthop.isra.0+0x3b3/0x3f0
+ __mkroute_output+0x43a/0x460
+ ip_route_output_key_hash+0xf7/0x140
+ ip_route_output_flow+0x1b/0x90
+ rxrpc_assess_MTU_size.isra.0+0x2a0/0x590
+ rxrpc_new_incoming_peer+0x46/0x120
+ rxrpc_alloc_incoming_call+0x1b1/0x400
+ rxrpc_new_incoming_call+0x1da/0x5e0
+ rxrpc_input_packet+0x827/0x900
+ rxrpc_io_thread+0x403/0xb60
+ kthread+0x2f7/0x310
+ ret_from_fork+0x2a/0x230
+ ret_from_fork_asm+0x1a/0x30
+...
+hardirqs last  enabled at (23): _raw_spin_unlock_irq+0x24/0x50
+hardirqs last disabled at (24): _raw_read_lock_irq+0x17/0x70
+softirqs last  enabled at (0): copy_process+0xc61/0x2730
+softirqs last disabled at (25): rt_add_uncached_list+0x3c/0x90
+
+Fix this by moving the call to rxrpc_assess_MTU_size() out of
+rxrpc_init_peer() and further up the stack where it can be done without
+interrupts disabled.
+
+It shouldn't be a problem for rxrpc_new_incoming_call() to do it after the
+locks are dropped as pmtud is going to be performed by the I/O thread - and
+we're in the I/O thread at this point.
+
+Fixes: a2ea9a907260 ("rxrpc: Use irq-disabling spinlocks between app and I/O thread")
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
+cc: Marc Dionne <marc.dionne@auristor.com>
+cc: Junvyyang, Tencent Zhuque Lab <zhuque@tencent.com>
+cc: LePremierHomme <kwqcheii@proton.me>
+cc: Simon Horman <horms@kernel.org>
+cc: linux-afs@lists.infradead.org
+Link: https://patch.msgid.link/20250717074350.3767366-2-dhowells@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ moved `peer->mtu`/`peer->maxdata` derivation into `rxrpc_assess_MTU_size()` at both exits since 6.12 predates the `max_data` rework ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/rxrpc/ar-internal.h |    1 +
+ net/rxrpc/call_accept.c |    1 +
+ net/rxrpc/peer_object.c |   12 +++++++-----
+ 3 files changed, 9 insertions(+), 5 deletions(-)
+
+--- a/net/rxrpc/ar-internal.h
++++ b/net/rxrpc/ar-internal.h
+@@ -1188,6 +1188,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu
+                                        const struct sockaddr_rxrpc *);
+ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *local,
+                                    struct sockaddr_rxrpc *srx, gfp_t gfp);
++void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer);
+ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t,
+                                   enum rxrpc_peer_trace);
+ void rxrpc_new_incoming_peer(struct rxrpc_local *local, struct rxrpc_peer *peer);
+--- a/net/rxrpc/call_accept.c
++++ b/net/rxrpc/call_accept.c
+@@ -407,6 +407,7 @@ bool rxrpc_new_incoming_call(struct rxrp
+       spin_unlock(&rx->incoming_lock);
+       read_unlock_irq(&local->services_lock);
++      rxrpc_assess_MTU_size(local, call->peer);
+       if (hlist_unhashed(&call->error_link)) {
+               spin_lock_irq(&call->peer->lock);
+--- a/net/rxrpc/peer_object.c
++++ b/net/rxrpc/peer_object.c
+@@ -147,8 +147,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu
+  * assess the MTU size for the network interface through which this peer is
+  * reached
+  */
+-static void rxrpc_assess_MTU_size(struct rxrpc_local *local,
+-                                struct rxrpc_peer *peer)
++void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer)
+ {
+       struct net *net = local->net;
+       struct dst_entry *dst;
+@@ -160,6 +159,8 @@ static void rxrpc_assess_MTU_size(struct
+ #endif
+       peer->if_mtu = 1500;
++      peer->mtu = peer->if_mtu;
++      peer->maxdata = peer->mtu - peer->hdrsize;
+       memset(&fl, 0, sizeof(fl));
+       switch (peer->srx.transport.family) {
+@@ -199,6 +200,9 @@ static void rxrpc_assess_MTU_size(struct
+       peer->if_mtu = dst_mtu(dst);
+       dst_release(dst);
++      peer->mtu = peer->if_mtu;
++      peer->maxdata = peer->mtu - peer->hdrsize;
++
+       _leave(" [if_mtu %u]", peer->if_mtu);
+ }
+@@ -240,8 +244,6 @@ static void rxrpc_init_peer(struct rxrpc
+                           unsigned long hash_key)
+ {
+       peer->hash_key = hash_key;
+-      rxrpc_assess_MTU_size(local, peer);
+-      peer->mtu = peer->if_mtu;
+       peer->rtt_last_req = ktime_get_real();
+       switch (peer->srx.transport.family) {
+@@ -266,7 +268,6 @@ static void rxrpc_init_peer(struct rxrpc
+       }
+       peer->hdrsize += sizeof(struct rxrpc_wire_header);
+-      peer->maxdata = peer->mtu - peer->hdrsize;
+ }
+ /*
+@@ -285,6 +286,7 @@ static struct rxrpc_peer *rxrpc_create_p
+       if (peer) {
+               memcpy(&peer->srx, srx, sizeof(*srx));
+               rxrpc_init_peer(local, peer, hash_key);
++              rxrpc_assess_MTU_size(local, peer);
+       }
+       _leave(" = %p", peer);
diff --git a/queue-6.6/sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch b/queue-6.6/sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch
new file mode 100644 (file)
index 0000000..15ad8b9
--- /dev/null
@@ -0,0 +1,134 @@
+From stable+bounces-297098-greg=kroah.com@vger.kernel.org Fri Aug  7 04:36:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 22:35:56 -0400
+Subject: sctp: avoid auth_enable sysctl UAF during netns teardown
+To: stable@vger.kernel.org
+Cc: Zhiling Zou <roxy520tt@gmail.com>, Yuan Tan <yuantan098@gmail.com>, Yifan Wu <yifanwucs@gmail.com>, Juefei Pu <tomapufckgml@gmail.com>, Xin Liu <bird@lzu.edu.cn>, Qi Tang <tpluszz77@gmail.com>, Ren Wei <n05ec@lzu.edu.cn>, Xin Long <lucien.xin@gmail.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807023556.1682974-2-sashal@kernel.org>
+
+From: Zhiling Zou <roxy520tt@gmail.com>
+
+[ Upstream commit f8d5e7846025f4ab15a461235f8ebae9094a361a ]
+
+proc_sctp_do_auth() updates the SCTP control socket after changing
+net.sctp.auth_enable. The handler gets the per-net SCTP state from
+ctl->data, so an already opened sysctl file can still target a network
+namespace while that namespace is being torn down.
+
+SCTP previously registered its per-net sysctls from sctp_defaults_init(),
+while the control socket is created later from sctp_ctrlsock_init(). This
+exposed a window during initialization where auth_enable was writable
+before net->sctp.ctl_sock existed, and a teardown window where auth_enable
+stayed writable after inet_ctl_sock_destroy() had released the control
+socket.
+
+Move the per-net SCTP sysctl registration into sctp_ctrlsock_init() after
+sctp_ctl_sock_init() succeeds, and unregister the sysctl table before
+destroying the control socket in sctp_ctrlsock_exit(). If sysctl
+registration fails after the control socket was created, destroy the
+control socket in the same init path.
+
+Make sctp_sysctl_net_unregister() tolerate a missing header and clear the
+saved pointer so init-error and exit paths can safely share the unregister
+helper.
+
+Fixes: 15649fd5415e ("sctp: sysctl: auth_enable: avoid using current->nsproxy")
+Cc: stable@vger.kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Co-developed-by: Qi Tang <tpluszz77@gmail.com>
+Signed-off-by: Qi Tang <tpluszz77@gmail.com>
+Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/390cd5e91ed60eea27b0b64d0468301a9e73b808.1784033357.git.roxy520tt@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/protocol.c |   20 ++++++++++++--------
+ net/sctp/sysctl.c   |    9 +++++++--
+ 2 files changed, 19 insertions(+), 10 deletions(-)
+
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -1394,10 +1394,6 @@ static int __net_init sctp_defaults_init
+       net->sctp.l3mdev_accept = 1;
+ #endif
+-      status = sctp_sysctl_net_register(net);
+-      if (status)
+-              goto err_sysctl_register;
+-
+       /* Allocate and initialise sctp mibs.  */
+       status = init_sctp_mibs(net);
+       if (status)
+@@ -1431,8 +1427,6 @@ err_init_proc:
+       cleanup_sctp_mibs(net);
+ #endif
+ err_init_mibs:
+-      sctp_sysctl_net_unregister(net);
+-err_sysctl_register:
+       return status;
+ }
+@@ -1447,7 +1441,6 @@ static void __net_exit sctp_defaults_exi
+       net->sctp.proc_net_sctp = NULL;
+ #endif
+       cleanup_sctp_mibs(net);
+-      sctp_sysctl_net_unregister(net);
+ }
+ static struct pernet_operations sctp_defaults_ops = {
+@@ -1461,16 +1454,27 @@ static int __net_init sctp_ctrlsock_init
+       /* Initialize the control inode/socket for handling OOTB packets.  */
+       status = sctp_ctl_sock_init(net);
+-      if (status)
++      if (status) {
+               pr_err("Failed to initialize the SCTP control sock\n");
++              return status;
++      }
++
++      status = sctp_sysctl_net_register(net);
++      if (status) {
++              inet_ctl_sock_destroy(net->sctp.ctl_sock);
++              net->sctp.ctl_sock = NULL;
++      }
+       return status;
+ }
+ static void __net_exit sctp_ctrlsock_exit(struct net *net)
+ {
++      sctp_sysctl_net_unregister(net);
++
+       /* Free the control endpoint.  */
+       inet_ctl_sock_destroy(net->sctp.ctl_sock);
++      net->sctp.ctl_sock = NULL;
+ }
+ static struct pernet_operations sctp_ctrlsock_ops = {
+--- a/net/sctp/sysctl.c
++++ b/net/sctp/sysctl.c
+@@ -630,11 +630,16 @@ int sctp_sysctl_net_register(struct net
+ void sctp_sysctl_net_unregister(struct net *net)
+ {
++      struct ctl_table_header *header = net->sctp.sysctl_header;
+       const struct ctl_table *table;
+-      table = net->sctp.sysctl_header->ctl_table_arg;
+-      unregister_net_sysctl_table(net->sctp.sysctl_header);
++      if (!header)
++              return;
++
++      table = header->ctl_table_arg;
++      unregister_net_sysctl_table(header);
+       kfree(table);
++      net->sctp.sysctl_header = NULL;
+ }
+ static struct ctl_table_header *sctp_sysctl_header;
diff --git a/queue-6.6/sctp-close-udp-tunnel-sockets-during-netns-teardown.patch b/queue-6.6/sctp-close-udp-tunnel-sockets-during-netns-teardown.patch
new file mode 100644 (file)
index 0000000..d42ee66
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-297287-greg=kroah.com@vger.kernel.org Fri Aug  7 13:55:49 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  7 Aug 2026 07:48:23 -0400
+Subject: sctp: close UDP tunnel sockets during netns teardown
+To: stable@vger.kernel.org
+Cc: Zhiling Zou <roxy520tt@gmail.com>, Sashiko <sashiko-bot@kernel.org>, Ren Wei <n05ec@lzu.edu.cn>, Xin Long <lucien.xin@gmail.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260807114823.2056694-3-sashal@kernel.org>
+
+From: Zhiling Zou <roxy520tt@gmail.com>
+
+[ Upstream commit ffb2bd7ade36ec4da32c46a6eddbf4515316d08c ]
+
+proc_sctp_do_udp_port() starts per-net SCTP UDP tunneling sockets when
+net.sctp.udp_port is set, and stops/restarts them when the sysctl value
+changes. The netns exit path does not stop these sockets, so a namespace
+can be torn down while its SCTP UDP tunnel sockets are still installed.
+
+Close the UDP tunnel sockets from sctp_ctrlsock_exit() after unregistering
+the per-net sysctl table. This prevents new sysctl writes from racing in
+while the sockets are being released, and closes the sockets before the
+control socket is destroyed.
+
+Fixes: 046c052b475e ("sctp: enable udp tunneling socks")
+Cc: stable@vger.kernel.org
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/b9f1f02b0780ad6a719e2413f5f0bb8eb7702d94.1782585631.git.roxy520tt%40gmail.com
+Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/6dab75f22855cb219e2e30a5497cab03b970ab91.1784033357.git.roxy520tt@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/protocol.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -1471,6 +1471,7 @@ static int __net_init sctp_ctrlsock_init
+ static void __net_exit sctp_ctrlsock_exit(struct net *net)
+ {
+       sctp_sysctl_net_unregister(net);
++      sctp_udp_sock_stop(net);
+       /* Free the control endpoint.  */
+       inet_ctl_sock_destroy(net->sctp.ctl_sock);
index eef58279d20a3bb16d1cc31e159edc64c1d5a6e0..0348a7ef1dfbac5f832d06ff8d97c12c6efc87b4 100644 (file)
@@ -211,3 +211,43 @@ mm-huge_memory-unlock-i_mmap_rwsem-before-releasing-.patch
 firmware-stratix10-svc-fix-memory-leaks-and-list-cor.patch
 gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch
 revert-ia64-make-acpi_cpufreq_cpu_exit-return-void.patch
+usb-musb-omap2430-clean-up-probe-error-handling.patch
+usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch
+drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch
+drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch
+usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch
+usb-typec-ucsi-only-enable-supported-notifications.patch
+usb-typec-ucsi-split-connector-lock-classes.patch
+usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch
+drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch
+drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch
+drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch
+drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch
+drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch
+media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch
+media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch
+media-i2c-imx219-drop-imx219_vts_-macros.patch
+media-i2c-imx219-group-functions-by-purpose.patch
+media-i2c-imx219-calculate-crop-rectangle-dynamically.patch
+media-i2c-imx219-rename-vts-to-frm_length.patch
+media-imx219-fix-maximum-frame-length-in-lines.patch
+rxrpc-fix-irq-disabled-in-local_bh_enable.patch
+netfilter-nf_tables-clone-set-on-flush-only.patch
+media-v4l-async-set-owner-for-async-sub-devices.patch
+media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch
+wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch
+wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch
+wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch
+wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch
+sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch
+sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch
+can-use-skb-hash-instead-of-private-variable-in-headroom.patch
+can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch
+libceph-add-doutc-and-_client-debug-macros-support.patch
+ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch
+ceph-fix-refcount-leak-in-ceph_readdir.patch
+mptcp-pm-avoid-code-duplication-to-lookup-endp.patch
+mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch
+mptcp-pm-use-addr-entry-for-get_local_id.patch
+mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch
+sctp-close-udp-tunnel-sockets-during-netns-teardown.patch
diff --git a/queue-6.6/sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch b/queue-6.6/sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch
new file mode 100644 (file)
index 0000000..b2b057b
--- /dev/null
@@ -0,0 +1,367 @@
+From stable+bounces-297097-greg=kroah.com@vger.kernel.org Fri Aug  7 04:36:09 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 22:35:55 -0400
+Subject: sysctl: treewide: constify ctl_table_header::ctl_table_arg
+To: stable@vger.kernel.org
+Cc: "Thomas Weißschuh" <linux@weissschuh.net>, "Kees Cook" <keescook@chromium.org>, "David S. Miller" <davem@davemloft.net>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260807023556.1682974-1-sashal@kernel.org>
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit bfa858f220ab8c950dd3e1310fee61950d0ecdae ]
+
+To be able to constify instances of struct ctl_tables it is necessary to
+remove ways through which non-const versions are exposed from the
+sysctl core.
+One of these is the ctl_table_arg member of struct ctl_table_header.
+
+Constify this reference as a prerequisite for the full constification of
+struct ctl_table instances.
+No functional change.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: f8d5e7846025 ("sctp: avoid auth_enable sysctl UAF during netns teardown")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/vrf.c                       |    2 +-
+ include/linux/sysctl.h                  |    2 +-
+ ipc/ipc_sysctl.c                        |    2 +-
+ ipc/mq_sysctl.c                         |    2 +-
+ kernel/ucount.c                         |    2 +-
+ net/ax25/sysctl_net_ax25.c              |    2 +-
+ net/bridge/br_netfilter_hooks.c         |    2 +-
+ net/core/sysctl_net_core.c              |    2 +-
+ net/ieee802154/6lowpan/reassembly.c     |    2 +-
+ net/ipv4/devinet.c                      |    2 +-
+ net/ipv4/ip_fragment.c                  |    2 +-
+ net/ipv4/route.c                        |    2 +-
+ net/ipv4/sysctl_net_ipv4.c              |    2 +-
+ net/ipv4/xfrm4_policy.c                 |    2 +-
+ net/ipv6/addrconf.c                     |    2 +-
+ net/ipv6/netfilter/nf_conntrack_reasm.c |    2 +-
+ net/ipv6/reassembly.c                   |    2 +-
+ net/ipv6/sysctl_net_ipv6.c              |    6 +++---
+ net/ipv6/xfrm6_policy.c                 |    2 +-
+ net/mpls/af_mpls.c                      |    4 ++--
+ net/mptcp/ctrl.c                        |    2 +-
+ net/netfilter/nf_conntrack_standalone.c |    2 +-
+ net/netfilter/nf_log.c                  |    2 +-
+ net/sctp/sysctl.c                       |    2 +-
+ net/smc/smc_sysctl.c                    |    2 +-
+ net/unix/sysctl_net_unix.c              |    2 +-
+ net/xfrm/xfrm_sysctl.c                  |    2 +-
+ 27 files changed, 30 insertions(+), 30 deletions(-)
+
+--- a/drivers/net/vrf.c
++++ b/drivers/net/vrf.c
+@@ -1983,7 +1983,7 @@ static int vrf_netns_init_sysctl(struct
+ static void vrf_netns_exit_sysctl(struct net *net)
+ {
+       struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = nn_vrf->ctl_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(nn_vrf->ctl_hdr);
+--- a/include/linux/sysctl.h
++++ b/include/linux/sysctl.h
+@@ -182,7 +182,7 @@ struct ctl_table_header {
+               struct rcu_head rcu;
+       };
+       struct completion *unregistering;
+-      struct ctl_table *ctl_table_arg;
++      const struct ctl_table *ctl_table_arg;
+       struct ctl_table_root *root;
+       struct ctl_table_set *set;
+       struct ctl_dir *parent;
+--- a/ipc/ipc_sysctl.c
++++ b/ipc/ipc_sysctl.c
+@@ -306,7 +306,7 @@ bool setup_ipc_sysctls(struct ipc_namesp
+ void retire_ipc_sysctls(struct ipc_namespace *ns)
+ {
+-      struct ctl_table *tbl;
++      const struct ctl_table *tbl;
+       tbl = ns->ipc_sysctls->ctl_table_arg;
+       unregister_sysctl_table(ns->ipc_sysctls);
+--- a/ipc/mq_sysctl.c
++++ b/ipc/mq_sysctl.c
+@@ -159,7 +159,7 @@ bool setup_mq_sysctls(struct ipc_namespa
+ void retire_mq_sysctls(struct ipc_namespace *ns)
+ {
+-      struct ctl_table *tbl;
++      const struct ctl_table *tbl;
+       tbl = ns->mq_sysctls->ctl_table_arg;
+       unregister_sysctl_table(ns->mq_sysctls);
+--- a/kernel/ucount.c
++++ b/kernel/ucount.c
+@@ -119,7 +119,7 @@ bool setup_userns_sysctls(struct user_na
+ void retire_userns_sysctls(struct user_namespace *ns)
+ {
+ #ifdef CONFIG_SYSCTL
+-      struct ctl_table *tbl;
++      const struct ctl_table *tbl;
+       tbl = ns->sysctls->ctl_table_arg;
+       unregister_sysctl_table(ns->sysctls);
+--- a/net/ax25/sysctl_net_ax25.c
++++ b/net/ax25/sysctl_net_ax25.c
+@@ -171,7 +171,7 @@ int ax25_register_dev_sysctl(ax25_dev *a
+ void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev)
+ {
+       struct ctl_table_header *header = ax25_dev->sysheader;
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       if (header) {
+               ax25_dev->sysheader = NULL;
+--- a/net/bridge/br_netfilter_hooks.c
++++ b/net/bridge/br_netfilter_hooks.c
+@@ -1290,7 +1290,7 @@ static int br_netfilter_sysctl_init_net(
+ static void br_netfilter_sysctl_exit_net(struct net *net,
+                                        struct brnf_net *brnet)
+ {
+-      struct ctl_table *table = brnet->ctl_hdr->ctl_table_arg;
++      const struct ctl_table *table = brnet->ctl_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(brnet->ctl_hdr);
+       if (!net_eq(net, &init_net))
+--- a/net/core/sysctl_net_core.c
++++ b/net/core/sysctl_net_core.c
+@@ -741,7 +741,7 @@ err_dup:
+ static __net_exit void sysctl_core_net_exit(struct net *net)
+ {
+-      struct ctl_table *tbl;
++      const struct ctl_table *tbl;
+       tbl = net->core.sysctl_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(net->core.sysctl_hdr);
+--- a/net/ieee802154/6lowpan/reassembly.c
++++ b/net/ieee802154/6lowpan/reassembly.c
+@@ -399,7 +399,7 @@ err_alloc:
+ static void __net_exit lowpan_frags_ns_sysctl_unregister(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       struct netns_ieee802154_lowpan *ieee802154_lowpan =
+               net_ieee802154_lowpan(net);
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -2793,7 +2793,7 @@ err_alloc_all:
+ static __net_exit void devinet_exit_net(struct net *net)
+ {
+ #ifdef CONFIG_SYSCTL
+-      struct ctl_table *tbl;
++      const struct ctl_table *tbl;
+       tbl = net->ipv4.forw_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(net->ipv4.forw_hdr);
+--- a/net/ipv4/ip_fragment.c
++++ b/net/ipv4/ip_fragment.c
+@@ -632,7 +632,7 @@ err_alloc:
+ static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = net->ipv4.frags_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(net->ipv4.frags_hdr);
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -3621,7 +3621,7 @@ err_dup:
+ static __net_exit void sysctl_route_net_exit(struct net *net)
+ {
+-      struct ctl_table *tbl;
++      const struct ctl_table *tbl;
+       tbl = net->ipv4.route_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(net->ipv4.route_hdr);
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -1564,7 +1564,7 @@ err_alloc:
+ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = net->ipv4.ipv4_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
+--- a/net/ipv4/xfrm4_policy.c
++++ b/net/ipv4/xfrm4_policy.c
+@@ -182,7 +182,7 @@ err_alloc:
+ static __net_exit void xfrm4_net_sysctl_exit(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       if (!net->ipv4.xfrm4_hdr)
+               return;
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -7251,7 +7251,7 @@ out:
+ static void __addrconf_sysctl_unregister(struct net *net,
+                                        struct ipv6_devconf *p, int ifindex)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       if (!p->sysctl_header)
+               return;
+--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
+@@ -105,7 +105,7 @@ err_alloc:
+ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
+ {
+       struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = nf_frag->nf_frag_frags_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(nf_frag->nf_frag_frags_hdr);
+--- a/net/ipv6/reassembly.c
++++ b/net/ipv6/reassembly.c
+@@ -487,7 +487,7 @@ err_alloc:
+ static void __net_exit ip6_frags_ns_sysctl_unregister(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = net->ipv6.sysctl.frags_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr);
+--- a/net/ipv6/sysctl_net_ipv6.c
++++ b/net/ipv6/sysctl_net_ipv6.c
+@@ -313,9 +313,9 @@ out_ipv6_table:
+ static void __net_exit ipv6_sysctl_net_exit(struct net *net)
+ {
+-      struct ctl_table *ipv6_table;
+-      struct ctl_table *ipv6_route_table;
+-      struct ctl_table *ipv6_icmp_table;
++      const struct ctl_table *ipv6_table;
++      const struct ctl_table *ipv6_route_table;
++      const struct ctl_table *ipv6_icmp_table;
+       ipv6_table = net->ipv6.sysctl.hdr->ctl_table_arg;
+       ipv6_route_table = net->ipv6.sysctl.route_hdr->ctl_table_arg;
+--- a/net/ipv6/xfrm6_policy.c
++++ b/net/ipv6/xfrm6_policy.c
+@@ -229,7 +229,7 @@ err_alloc:
+ static void __net_exit xfrm6_net_sysctl_exit(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       if (!net->ipv6.sysctl.xfrm6_hdr)
+               return;
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -1422,7 +1422,7 @@ static void mpls_dev_sysctl_unregister(s
+                                      struct mpls_dev *mdev)
+ {
+       struct net *net = dev_net(dev);
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       if (!mdev->sysctl)
+               return;
+@@ -2692,7 +2692,7 @@ static void mpls_net_exit(struct net *ne
+ {
+       struct mpls_route __rcu **platform_label;
+       size_t platform_labels;
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       unsigned int index;
+       table = net->mpls.ctl->ctl_table_arg;
+--- a/net/mptcp/ctrl.c
++++ b/net/mptcp/ctrl.c
+@@ -218,7 +218,7 @@ err_alloc:
+ static void mptcp_pernet_del_table(struct mptcp_pernet *pernet)
+ {
+-      struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
++      const struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(pernet->ctl_table_hdr);
+--- a/net/netfilter/nf_conntrack_standalone.c
++++ b/net/netfilter/nf_conntrack_standalone.c
+@@ -1113,7 +1113,7 @@ out_unregister_netfilter:
+ static void nf_conntrack_standalone_fini_sysctl(struct net *net)
+ {
+       struct nf_conntrack_net *cnet = nf_ct_pernet(net);
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = cnet->sysctl_header->ctl_table_arg;
+       unregister_net_sysctl_table(cnet->sysctl_header);
+--- a/net/netfilter/nf_log.c
++++ b/net/netfilter/nf_log.c
+@@ -509,7 +509,7 @@ err_alloc:
+ static void netfilter_log_sysctl_exit(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = net->nf.nf_log_dir_header->ctl_table_arg;
+       unregister_net_sysctl_table(net->nf.nf_log_dir_header);
+--- a/net/sctp/sysctl.c
++++ b/net/sctp/sysctl.c
+@@ -630,7 +630,7 @@ int sctp_sysctl_net_register(struct net
+ void sctp_sysctl_net_unregister(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = net->sctp.sysctl_header->ctl_table_arg;
+       unregister_net_sysctl_table(net->sctp.sysctl_header);
+--- a/net/smc/smc_sysctl.c
++++ b/net/smc/smc_sysctl.c
+@@ -109,7 +109,7 @@ err_alloc:
+ void __net_exit smc_sysctl_net_exit(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = net->smc.smc_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(net->smc.smc_hdr);
+--- a/net/unix/sysctl_net_unix.c
++++ b/net/unix/sysctl_net_unix.c
+@@ -52,7 +52,7 @@ err_alloc:
+ void unix_sysctl_unregister(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = net->unx.ctl->ctl_table_arg;
+       unregister_net_sysctl_table(net->unx.ctl);
+--- a/net/xfrm/xfrm_sysctl.c
++++ b/net/xfrm/xfrm_sysctl.c
+@@ -76,7 +76,7 @@ out_kmemdup:
+ void __net_exit xfrm_sysctl_fini(struct net *net)
+ {
+-      struct ctl_table *table;
++      const struct ctl_table *table;
+       table = net->xfrm.sysctl_hdr->ctl_table_arg;
+       unregister_net_sysctl_table(net->xfrm.sysctl_hdr);
diff --git a/queue-6.6/usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch b/queue-6.6/usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch
new file mode 100644 (file)
index 0000000..ec765cd
--- /dev/null
@@ -0,0 +1,388 @@
+From sashal@kernel.org Thu Jul 30 21:39:06 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 15:39:02 -0400
+Subject: usb: gadget: f_tcm: synchronize delayed set_alt with teardown
+To: stable@vger.kernel.org
+Cc: Cen Zhang <zzzccc427@gmail.com>, stable <stable@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260730193902.3130410-1-sashal@kernel.org>
+
+From: Cen Zhang <zzzccc427@gmail.com>
+
+[ Upstream commit 79e2d75725c85607f8a9d87ae9cace62a19f767d ]
+
+The f_tcm set_alt() path defers endpoint setup to a work item and
+completes the delayed status response from process context. The delayed
+work uses f_tcm private state and may complete the setup request after
+disconnect or function teardown has already moved on.
+
+Cancel and drain the delayed set_alt work when the function is unbound or
+freed. For disable paths, which are reached under the composite device
+lock, use a small state machine and a non-sleeping cancellation path
+instead of cancel_work_sync(). If the work is already running, mark it
+cancelled and let the worker own the cleanup; otherwise tcm_disable() can
+cancel the queued work and clean up immediately.
+
+Also serialize the final delayed-status completion with the cancellation
+check while holding the composite device lock. This prevents a disconnect
+from clearing delayed_status while the worker is about to complete the
+control request.
+
+Validation reproduced this kernel report:
+BUG: KASAN: slab-use-after-free in tcm_delayed_set_alt+0x6c/0xef0
+
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x66/0xa0
+ print_report+0xce/0x630
+ ? tcm_delayed_set_alt+0x6c/0xef0
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __virt_addr_valid+0x188/0x320
+ ? tcm_delayed_set_alt+0x6c/0xef0
+ kasan_report+0xe0/0x110
+ ? tcm_delayed_set_alt+0x6c/0xef0
+ tcm_delayed_set_alt+0x6c/0xef0
+ ? __pfx_tcm_delayed_set_alt+0x10/0x10
+ ? process_one_work+0x4cb/0xb90
+ ? rcu_is_watching+0x20/0x50
+ ? tcm_delayed_set_alt+0x9/0xef0
+ process_one_work+0x4d7/0xb90
+ ? __pfx_process_one_work+0x10/0x10
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __list_add_valid_or_report+0x37/0xf0
+ ? __pfx_tcm_delayed_set_alt+0x10/0x10
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ worker_thread+0x2d8/0x570
+ ? __pfx_worker_thread+0x10/0x10
+ kthread+0x1ad/0x1f0
+ ? __pfx_kthread+0x10/0x10
+ ret_from_fork+0x3c9/0x540
+ ? __pfx_ret_from_fork+0x10/0x10
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __switch_to+0x2e9/0x730
+ ? __pfx_kthread+0x10/0x10
+ ret_from_fork_asm+0x1a/0x30
+ </TASK>
+
+Allocated by task 544:
+ kasan_save_stack+0x33/0x60
+ kasan_save_track+0x14/0x30
+ __kasan_kmalloc+0x8f/0xa0
+ tcm_alloc+0x68/0x180
+ usb_get_function+0x36/0x60
+ config_usb_cfg_link+0x125/0x1b0
+ configfs_symlink+0x322/0x890
+ vfs_symlink+0xc2/0x270
+ filename_symlinkat+0x295/0x2f0
+ __x64_sys_symlinkat+0x62/0x90
+ do_syscall_64+0x115/0x6a0
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Freed by task 661:
+ kasan_save_stack+0x33/0x60
+ kasan_save_track+0x14/0x30
+ kasan_save_free_info+0x3b/0x60
+ __kasan_slab_free+0x43/0x70
+ kfree+0x2f9/0x530
+ config_usb_cfg_unlink+0x173/0x1e0
+ configfs_unlink+0x1fa/0x340
+ vfs_unlink+0x15c/0x510
+ filename_unlinkat+0x2ba/0x450
+ __x64_sys_unlinkat+0x63/0x90
+ do_syscall_64+0x115/0x6a0
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: c52661d60f63 ("usb-gadget: Initial merge of target module for UASP + BOT")
+Cc: stable <stable@kernel.org>
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
+Link: https://patch.msgid.link/20260627104153.3822495-1-zzzccc427@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ adjusted context for 6.12's scalar `struct usbg_cdb cmd` and missing `stream_hash`, dropping the `hash_init()` context line ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_tcm.c |  192 ++++++++++++++++++++++++++++++------
+ drivers/usb/gadget/function/tcm.h   |   13 ++
+ 2 files changed, 177 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_tcm.c
++++ b/drivers/usb/gadget/function/f_tcm.c
+@@ -2011,31 +2011,158 @@ ep_fail:
+       return -ENOTSUPP;
+ }
+-struct guas_setup_wq {
+-      struct work_struct work;
+-      struct f_uas *fu;
+-      unsigned int alt;
+-};
++static void tcm_cleanup_old_alt(struct f_uas *fu)
++{
++      if (fu->flags & USBG_IS_UAS)
++              uasp_cleanup_old_alt(fu);
++      else if (fu->flags & USBG_IS_BOT)
++              bot_cleanup_old_alt(fu);
++      fu->flags = 0;
++}
++
++static void tcm_delayed_set_alt_done(struct f_uas *fu)
++{
++      unsigned long flags;
++
++      spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
++      fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
++      fu->delayed_set_alt_cancel = false;
++      spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
++}
++
++static bool tcm_delayed_set_alt_cancelled(struct f_uas *fu)
++{
++      bool cancelled;
++      unsigned long flags;
++
++      spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
++      cancelled = fu->delayed_set_alt_cancel;
++      spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
++
++      return cancelled;
++}
++
++static bool tcm_complete_delayed_status(struct f_uas *fu)
++{
++      struct usb_composite_dev *cdev = fu->function.config->cdev;
++      struct usb_request *req = cdev->req;
++      unsigned long cdev_flags;
++      bool cancelled;
++      int ret;
++
++      spin_lock_irqsave(&cdev->lock, cdev_flags);
++      spin_lock(&fu->delayed_set_alt_lock);
++      cancelled = fu->delayed_set_alt_cancel;
++      if (!cancelled) {
++              fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
++              fu->delayed_set_alt_cancel = false;
++      }
++      spin_unlock(&fu->delayed_set_alt_lock);
++
++      if (cancelled) {
++              spin_unlock_irqrestore(&cdev->lock, cdev_flags);
++              return false;
++      }
++
++      if (cdev->delayed_status == 0) {
++              WARN(cdev, "%s: Unexpected call\n", __func__);
++      } else if (--cdev->delayed_status == 0) {
++              req->length = 0;
++              req->context = cdev;
++              ret = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
++              if (ret == 0) {
++                      cdev->setup_pending = true;
++              } else {
++                      req->status = 0;
++                      req->complete(cdev->gadget->ep0, req);
++              }
++      }
++
++      spin_unlock_irqrestore(&cdev->lock, cdev_flags);
++
++      return true;
++}
++
++static bool tcm_cancel_delayed_set_alt(struct f_uas *fu)
++{
++      bool cleanup = false;
++      bool cancel = false;
++      unsigned long flags;
++
++      spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
++      switch (fu->delayed_set_alt_state) {
++      case USBG_DELAYED_SET_ALT_IDLE:
++              cleanup = true;
++              break;
++      case USBG_DELAYED_SET_ALT_QUEUED:
++      case USBG_DELAYED_SET_ALT_RUNNING:
++              fu->delayed_set_alt_cancel = true;
++              cancel = true;
++              break;
++      }
++      spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
++
++      if (cancel && cancel_work(&fu->delayed_set_alt)) {
++              spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
++              if (fu->delayed_set_alt_state == USBG_DELAYED_SET_ALT_QUEUED) {
++                      fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
++                      fu->delayed_set_alt_cancel = false;
++                      cleanup = true;
++              }
++              spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
++      }
++
++      return cleanup;
++}
++
++static void tcm_cancel_delayed_set_alt_sync(struct f_uas *fu)
++{
++      unsigned long flags;
++
++      spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
++      if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_IDLE)
++              fu->delayed_set_alt_cancel = true;
++      spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
++
++      cancel_work_sync(&fu->delayed_set_alt);
++
++      spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
++      fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
++      fu->delayed_set_alt_cancel = false;
++      spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
++}
+ static void tcm_delayed_set_alt(struct work_struct *wq)
+ {
+-      struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq,
+-                      work);
+-      struct f_uas *fu = work->fu;
+-      int alt = work->alt;
++      struct f_uas *fu = container_of(wq, struct f_uas, delayed_set_alt);
++      unsigned long flags;
++      unsigned int alt;
++
++      spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
++      if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_QUEUED) {
++              spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
++              return;
++      }
++      fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_RUNNING;
++      alt = fu->delayed_alt;
++      spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+-      kfree(work);
++      tcm_cleanup_old_alt(fu);
+-      if (fu->flags & USBG_IS_BOT)
+-              bot_cleanup_old_alt(fu);
+-      if (fu->flags & USBG_IS_UAS)
+-              uasp_cleanup_old_alt(fu);
++      if (tcm_delayed_set_alt_cancelled(fu))
++              goto out_done;
+       if (alt == USB_G_ALT_INT_BBB)
+               bot_set_alt(fu);
+       else if (alt == USB_G_ALT_INT_UAS)
+               uasp_set_alt(fu);
+-      usb_composite_setup_continue(fu->function.config->cdev);
++
++      if (tcm_complete_delayed_status(fu))
++              return;
++
++      tcm_cleanup_old_alt(fu);
++out_done:
++      tcm_delayed_set_alt_done(fu);
+ }
+ static int tcm_get_alt(struct usb_function *f, unsigned intf)
+@@ -2061,15 +2188,20 @@ static int tcm_set_alt(struct usb_functi
+               return -EOPNOTSUPP;
+       if ((alt == USB_G_ALT_INT_BBB) || (alt == USB_G_ALT_INT_UAS)) {
+-              struct guas_setup_wq *work;
++              unsigned long flags;
++
++              spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
++              if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_IDLE) {
++                      spin_unlock_irqrestore(&fu->delayed_set_alt_lock,
++                                             flags);
++                      return -EBUSY;
++              }
++              fu->delayed_alt = alt;
++              fu->delayed_set_alt_cancel = false;
++              fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_QUEUED;
++              spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+-              work = kmalloc(sizeof(*work), GFP_ATOMIC);
+-              if (!work)
+-                      return -ENOMEM;
+-              INIT_WORK(&work->work, tcm_delayed_set_alt);
+-              work->fu = fu;
+-              work->alt = alt;
+-              schedule_work(&work->work);
++              schedule_work(&fu->delayed_set_alt);
+               return USB_GADGET_DELAYED_STATUS;
+       }
+       return -EOPNOTSUPP;
+@@ -2079,11 +2211,8 @@ static void tcm_disable(struct usb_funct
+ {
+       struct f_uas *fu = to_f_uas(f);
+-      if (fu->flags & USBG_IS_UAS)
+-              uasp_cleanup_old_alt(fu);
+-      else if (fu->flags & USBG_IS_BOT)
+-              bot_cleanup_old_alt(fu);
+-      fu->flags = 0;
++      if (tcm_cancel_delayed_set_alt(fu))
++              tcm_cleanup_old_alt(fu);
+ }
+ static int tcm_setup(struct usb_function *f,
+@@ -2231,11 +2360,16 @@ static void tcm_free(struct usb_function
+ {
+       struct f_uas *tcm = to_f_uas(f);
++      tcm_cancel_delayed_set_alt_sync(tcm);
+       kfree(tcm);
+ }
+ static void tcm_unbind(struct usb_configuration *c, struct usb_function *f)
+ {
++      struct f_uas *fu = to_f_uas(f);
++
++      tcm_cancel_delayed_set_alt_sync(fu);
++      tcm_cleanup_old_alt(fu);
+       usb_free_all_descriptors(f);
+ }
+@@ -2268,6 +2402,8 @@ static struct usb_function *tcm_alloc(st
+       fu->function.disable = tcm_disable;
+       fu->function.free_func = tcm_free;
+       fu->tpg = tpg_instances[i].tpg;
++      INIT_WORK(&fu->delayed_set_alt, tcm_delayed_set_alt);
++      spin_lock_init(&fu->delayed_set_alt_lock);
+       mutex_unlock(&tpg_instances_lock);
+       return &fu->function;
+--- a/drivers/usb/gadget/function/tcm.h
++++ b/drivers/usb/gadget/function/tcm.h
+@@ -3,6 +3,7 @@
+ #define __TARGET_USB_GADGET_H__
+ #include <linux/kref.h>
++#include <linux/spinlock.h>
+ /* #include <linux/usb/uas.h> */
+ #include <linux/usb/composite.h>
+ #include <linux/usb/uas.h>
+@@ -26,6 +27,12 @@ enum {
+ #define USB_G_DEFAULT_SESSION_TAGS    128
++enum {
++      USBG_DELAYED_SET_ALT_IDLE = 0,
++      USBG_DELAYED_SET_ALT_QUEUED,
++      USBG_DELAYED_SET_ALT_RUNNING,
++};
++
+ struct tcm_usbg_nexus {
+       struct se_session *tvn_se_sess;
+ };
+@@ -117,6 +124,12 @@ struct f_uas {
+ #define USBG_IS_BOT           (1 << 3)
+ #define USBG_BOT_CMD_PEND     (1 << 4)
++      struct work_struct      delayed_set_alt;
++      spinlock_t              delayed_set_alt_lock; /* protects delayed_set_alt_* */
++      unsigned int            delayed_alt;
++      unsigned int            delayed_set_alt_state;
++      bool                    delayed_set_alt_cancel;
++
+       struct usbg_cdb         cmd;
+       struct usb_ep           *ep_in;
+       struct usb_ep           *ep_out;
diff --git a/queue-6.6/usb-musb-omap2430-clean-up-probe-error-handling.patch b/queue-6.6/usb-musb-omap2430-clean-up-probe-error-handling.patch
new file mode 100644 (file)
index 0000000..07c6cc7
--- /dev/null
@@ -0,0 +1,103 @@
+From sashal@kernel.org Thu Jul 30 15:13:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 09:13:35 -0400
+Subject: usb: musb: omap2430: clean up probe error handling
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260730131336.2345145-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 51d4b0a44c82e5eff056ef76acd2c3c605a8eb74 ]
+
+Using numbered error labels is discouraged (e.g. as it requires
+renumbering them when adding a new intermediate error path).
+
+Rename the error labels after what they do.
+
+While at it, drop the redundant platform allocation failure dev_err()
+as the error would already have been logged by the allocator.
+
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://lore.kernel.org/r/20250724091910.21092-6-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: c947360ae63e ("usb: musb: omap2430: Do not put borrowed of_node in probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/musb/omap2430.c |   23 ++++++++++-------------
+ 1 file changed, 10 insertions(+), 13 deletions(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -318,13 +318,11 @@ static int omap2430_probe(struct platfor
+       glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
+       if (!glue)
+-              goto err0;
++              return -ENOMEM;
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
+-      if (!musb) {
+-              dev_err(&pdev->dev, "failed to allocate musb device\n");
+-              goto err0;
+-      }
++      if (!musb)
++              return -ENOMEM;
+       musb->dev.parent                = &pdev->dev;
+       musb->dev.dma_mask              = &omap2430_dmamask;
+@@ -348,15 +346,15 @@ static int omap2430_probe(struct platfor
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+-              goto err2;
++              goto err_put_musb;
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+-              goto err2;
++              goto err_put_musb;
+       config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
+       if (!config)
+-              goto err2;
++              goto err_put_musb;
+       of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
+       of_property_read_u32(np, "interface-type",
+@@ -379,7 +377,7 @@ static int omap2430_probe(struct platfor
+               if (!control_pdev) {
+                       dev_err(&pdev->dev, "Failed to get control device\n");
+                       ret = -EINVAL;
+-                      goto err2;
++                      goto err_put_musb;
+               }
+               glue->control_otghs = &control_pdev->dev;
+       }
+@@ -455,22 +453,21 @@ static int omap2430_probe(struct platfor
+       ret = platform_device_add(musb);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register musb device\n");
+-              goto err3;
++              goto err_disable_rpm;
+       }
+       of_node_put(np);
+       return 0;
+-err3:
++err_disable_rpm:
+       pm_runtime_disable(glue->dev);
+ err_put_control_otghs:
+       if (!IS_ERR(glue->control_otghs))
+               put_device(glue->control_otghs);
+-err2:
++err_put_musb:
+       of_node_put(np);
+       platform_device_put(musb);
+-err0:
+       return ret;
+ }
diff --git a/queue-6.6/usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch b/queue-6.6/usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch
new file mode 100644 (file)
index 0000000..9b064c1
--- /dev/null
@@ -0,0 +1,54 @@
+From sashal@kernel.org Thu Jul 30 15:13:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 09:13:36 -0400
+Subject: usb: musb: omap2430: Do not put borrowed of_node in probe
+To: stable@vger.kernel.org
+Cc: Guangshuo Li <lgs201920130244@gmail.com>, stable <stable@kernel.org>, Johan Hovold <johan@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260730131336.2345145-2-sashal@kernel.org>
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit c947360ae63eee1c9eacc030dd6f5a53f717addf ]
+
+omap2430_probe() stores pdev->dev.of_node in a local np variable. This is
+a borrowed pointer and the probe function does not take a reference to
+it.
+
+The success and error paths nevertheless call of_node_put(np). This drops
+a reference that is owned by the platform device, and can leave
+pdev->dev.of_node with an unbalanced reference count.
+
+Do not put the borrowed platform device node from omap2430_probe().
+References taken for the child MUSB device are handled by the device core,
+and the ctrl-module phandle reference is still released separately.
+
+Fixes: ffbe2feac59b ("usb: musb: omap2430: Fix probe regression for missing resources")
+Cc: stable <stable@kernel.org>
+Reviewed-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Link: https://patch.msgid.link/20260713114711.955253-1-lgs201920130244@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/musb/omap2430.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -455,7 +455,6 @@ static int omap2430_probe(struct platfor
+               dev_err(&pdev->dev, "failed to register musb device\n");
+               goto err_disable_rpm;
+       }
+-      of_node_put(np);
+       return 0;
+@@ -465,7 +464,6 @@ err_put_control_otghs:
+       if (!IS_ERR(glue->control_otghs))
+               put_device(glue->control_otghs);
+ err_put_musb:
+-      of_node_put(np);
+       platform_device_put(musb);
+       return ret;
diff --git a/queue-6.6/usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch b/queue-6.6/usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch
new file mode 100644 (file)
index 0000000..3b51fba
--- /dev/null
@@ -0,0 +1,173 @@
+From stable+bounces-293910-greg=kroah.com@vger.kernel.org Fri Jul 31 04:41:04 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 22:40:57 -0400
+Subject: usb: typec: ucsi: Fix race condition and ordering in port unregistration
+To: stable@vger.kernel.org
+Cc: Andrei Kuchynski <akuchynski@chromium.org>, stable <stable@kernel.org>, Benson Leung <bleung@chromium.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260731024057.3338855-3-sashal@kernel.org>
+
+From: Andrei Kuchynski <akuchynski@chromium.org>
+
+[ Upstream commit 7aa7d4bf9d3fa9a6a47b640ad103ab433b7ff261 ]
+
+A synchronization issue exists during port unregistration where pending
+partner work items can race against workqueue destruction, leading to
+use-after-free conditions:
+
+  cros_ec_ucsi cros_ec_ucsi.3.auto: error -ETIMEDOUT: PPM init failed
+  BUG: kernel NULL pointer dereference, address: 0000000000000000
+  RIP: 0010:__queue_work+0x83/0x4a0
+  Call Trace:
+    <IRQ>
+    __cfi_delayed_work_timer_fn+0x10/0x10
+    run_timer_softirq+0x3b6/0xbd0
+    sched_clock_cpu+0xc/0x110
+    irq_exit_rcu+0x18d/0x330
+    fred_sysvec_apic_timer_interrupt+0x5e/0x80
+
+Fix this by ensuring strict ordering and proper serialization during
+teardown:
+
+1. Move ucsi_unregister_partner() to the beginning of the teardown
+sequence and protect it under the connector mutex lock.
+2. Ensure all pending partner tasks are explicitly flushed and finished
+before the workqueue is destroyed.
+3. Switch from mod_delayed_work() to a cancel_delayed_work() and
+queue_delayed_work() sequence. This guarantees that items currently marked
+as pending won't be scheduled an additional time, preventing a double
+release of resources which leads to the following crash:
+
+  Oops: general protection fault, probably for non-canonical address
+    0xdead000000000122: 0000 [#1] SMP NOPTI
+  Workqueue: cros_ec_ucsi.3.auto-con2 ucsi_poll_worker
+  RIP: 0010:ucsi_poll_worker+0x65/0x1e0
+  Call Trace:
+  <TASK>
+    process_scheduled_works+0x218/0x6d0
+    worker_thread+0x188/0x3f0
+    __cfi_worker_thread+0x10/0x10
+    kthread+0x226/0x2a0
+
+To ensure these rules are applied identically across both the normal
+teardown and the ucsi_init() error paths, consolidate the cleanup logic
+into a new helper, ucsi_unregister_port().
+
+Cc: stable <stable@kernel.org>
+Fixes: b9aa02ca39a4 ("usb: typec: ucsi: Add polling mechanism for partner tasks like alt mode checking")
+Fixes: b13abcb7ddd8 ("usb: typec: ucsi: Fix NULL pointer access")
+Fixes: fac4b8633fd6 ("usb: ucsi: Ensure connector delayed work items are flushed")
+Signed-off-by: Andrei Kuchynski <akuchynski@chromium.org>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Link: https://patch.msgid.link/20260707141736.1635698-1-akuchynski@chromium.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |   82 +++++++++++++++++++-----------------------
+ 1 file changed, 39 insertions(+), 43 deletions(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -1407,6 +1407,42 @@ out_unlock:
+       return ret;
+ }
++static void ucsi_unregister_port(struct ucsi_connector *con)
++{
++      struct ucsi_work *uwork;
++
++      if (con->wq) {
++              mutex_lock(&con->lock);
++              ucsi_unregister_partner(con);
++              /*
++               * queue delayed items immediately so they can execute
++               * and free themselves before the wq is destroyed
++               */
++              list_for_each_entry(uwork, &con->partner_tasks, node) {
++                      if (cancel_delayed_work(&uwork->work))
++                              queue_delayed_work(con->wq, &uwork->work, 0);
++              }
++              mutex_unlock(&con->lock);
++
++              destroy_workqueue(con->wq);
++              con->wq = NULL;
++      } else {
++              ucsi_unregister_partner(con);
++      }
++
++      ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
++      ucsi_unregister_port_psy(con);
++
++      usb_power_delivery_unregister_capabilities(con->port_sink_caps);
++      con->port_sink_caps = NULL;
++      usb_power_delivery_unregister_capabilities(con->port_source_caps);
++      con->port_source_caps = NULL;
++      usb_power_delivery_unregister(con->pd);
++      con->pd = NULL;
++      typec_unregister_port(con->port);
++      con->port = NULL;
++}
++
+ static u64 ucsi_get_supported_notifications(struct ucsi *ucsi)
+ {
+       u8 features = ucsi->cap.features;
+@@ -1515,22 +1551,8 @@ err_unregister:
+       for (i = 0; i < ucsi->cap.num_connectors; i++)
+               lockdep_unregister_key(&connector[i].lock_key);
+-      for (con = connector; con->port; con++) {
+-              if (con->wq)
+-                      destroy_workqueue(con->wq);
+-              ucsi_unregister_partner(con);
+-              ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
+-              ucsi_unregister_port_psy(con);
+-
+-              usb_power_delivery_unregister_capabilities(con->port_sink_caps);
+-              con->port_sink_caps = NULL;
+-              usb_power_delivery_unregister_capabilities(con->port_source_caps);
+-              con->port_source_caps = NULL;
+-              usb_power_delivery_unregister(con->pd);
+-              con->pd = NULL;
+-              typec_unregister_port(con->port);
+-              con->port = NULL;
+-      }
++      for (con = connector; con->port; con++)
++              ucsi_unregister_port(con);
+       kfree(connector);
+ err_reset:
+       memset(&ucsi->cap, 0, sizeof(ucsi->cap));
+@@ -1756,33 +1778,7 @@ void ucsi_unregister(struct ucsi *ucsi)
+       for (i = 0; i < ucsi->cap.num_connectors; i++) {
+               cancel_work_sync(&ucsi->connector[i].work);
+-
+-              if (ucsi->connector[i].wq) {
+-                      struct ucsi_work *uwork;
+-
+-                      mutex_lock(&ucsi->connector[i].lock);
+-                      /*
+-                       * queue delayed items immediately so they can execute
+-                       * and free themselves before the wq is destroyed
+-                       */
+-                      list_for_each_entry(uwork, &ucsi->connector[i].partner_tasks, node)
+-                              mod_delayed_work(ucsi->connector[i].wq, &uwork->work, 0);
+-                      mutex_unlock(&ucsi->connector[i].lock);
+-                      destroy_workqueue(ucsi->connector[i].wq);
+-              }
+-
+-              ucsi_unregister_partner(&ucsi->connector[i]);
+-              ucsi_unregister_altmodes(&ucsi->connector[i],
+-                                       UCSI_RECIPIENT_CON);
+-              ucsi_unregister_port_psy(&ucsi->connector[i]);
+-
+-              usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_sink_caps);
+-              ucsi->connector[i].port_sink_caps = NULL;
+-              usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_source_caps);
+-              ucsi->connector[i].port_source_caps = NULL;
+-              usb_power_delivery_unregister(ucsi->connector[i].pd);
+-              ucsi->connector[i].pd = NULL;
+-              typec_unregister_port(ucsi->connector[i].port);
++              ucsi_unregister_port(&ucsi->connector[i]);
+               lockdep_unregister_key(&ucsi->connector[i].lock_key);
+       }
diff --git a/queue-6.6/usb-typec-ucsi-only-enable-supported-notifications.patch b/queue-6.6/usb-typec-ucsi-only-enable-supported-notifications.patch
new file mode 100644 (file)
index 0000000..cdfebad
--- /dev/null
@@ -0,0 +1,68 @@
+From sashal@kernel.org Fri Jul 31 04:41:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 22:40:55 -0400
+Subject: usb: typec: ucsi: Only enable supported notifications
+To: stable@vger.kernel.org
+Cc: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>, Heikki Krogerus <heikki.krogerus@linux.intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260731024057.3338855-1-sashal@kernel.org>
+
+From: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
+
+[ Upstream commit 27ffe4ff0b33b3dcc97fd448fd1e38d31ade575b ]
+
+The UCSI specification defines some notifications to be optional for the
+PPM to support. From these only enable the ones the PPM informs us are
+actually supported.
+
+Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/yhz7nq622mbg3rqsyvqz632pc756niagpfbnzayfswhzo7esho@vrdtx5c3hjgx
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 7aa7d4bf9d3f ("usb: typec: ucsi: Fix race condition and ordering in port unregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |   25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -1406,6 +1406,27 @@ out_unlock:
+       return ret;
+ }
++static u64 ucsi_get_supported_notifications(struct ucsi *ucsi)
++{
++      u8 features = ucsi->cap.features;
++      u64 ntfy = UCSI_ENABLE_NTFY_ALL;
++
++      if (!(features & UCSI_CAP_ALT_MODE_DETAILS))
++              ntfy &= ~UCSI_ENABLE_NTFY_CAM_CHANGE;
++
++      if (!(features & UCSI_CAP_PDO_DETAILS))
++              ntfy &= ~(UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE |
++                        UCSI_ENABLE_NTFY_CAP_CHANGE);
++
++      if (!(features & UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS))
++              ntfy &= ~UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE;
++
++      if (!(features & UCSI_CAP_PD_RESET))
++              ntfy &= ~UCSI_ENABLE_NTFY_PD_RESET_COMPLETE;
++
++      return ntfy;
++}
++
+ /**
+  * ucsi_init - Initialize UCSI interface
+  * @ucsi: UCSI to be initialized
+@@ -1466,8 +1487,8 @@ static int ucsi_init(struct ucsi *ucsi)
+                       goto err_unregister;
+       }
+-      /* Enable all notifications */
+-      ntfy = UCSI_ENABLE_NTFY_ALL;
++      /* Enable all supported notifications */
++      ntfy = ucsi_get_supported_notifications(ucsi);
+       command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
+       ret = ucsi_send_command(ucsi, command, NULL, 0);
+       if (ret < 0)
diff --git a/queue-6.6/usb-typec-ucsi-split-connector-lock-classes.patch b/queue-6.6/usb-typec-ucsi-split-connector-lock-classes.patch
new file mode 100644 (file)
index 0000000..80a57a8
--- /dev/null
@@ -0,0 +1,124 @@
+From sashal@kernel.org Fri Jul 31 04:41:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jul 2026 22:40:56 -0400
+Subject: usb: typec: ucsi: split connector lock classes
+To: stable@vger.kernel.org
+Cc: Sergey Senozhatsky <senozhatsky@chromium.org>, Heikki Krogerus <heikki.krogerus@linux.intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260731024057.3338855-2-sashal@kernel.org>
+
+From: Sergey Senozhatsky <senozhatsky@chromium.org>
+
+[ Upstream commit 8c22256bbafad3dc5fdbe9f684d045b67ff06a68 ]
+
+Lockdep detects a possible recursive locking scenario during
+ucsi init:
+
+[    5.418616] ============================================
+[    5.418634] WARNING: possible recursive locking detected
+[    5.418706] --------------------------------------------
+[    5.418725] kworker/4:1/82 is trying to acquire lock:
+[    5.418759] ffff888119a34648 (&con->lock){+.+.}-{3:3}, at: ucsi_init_work+0x1a78/0x2eb0 [typec_ucsi]
+[    5.418801]
+               but task is already holding lock:
+[    5.418835] ffff888119a34080 (&con->lock){+.+.}-{3:3}, at: ucsi_init_work+0x1a78/0x2eb0 [typec_ucsi]
+[    5.418884]
+               other info that might help us debug this:
+[    5.418904]  Possible unsafe locking scenario:
+
+[    5.418937]        CPU0
+[    5.418956]        ----
+[    5.418991]   lock(&con->lock);
+[    5.419013]   lock(&con->lock);
+[    5.419033]
+                *** DEADLOCK ***
+
+[    5.419387] Call Trace:
+[    5.419406]  <TASK>
+[    5.419425]  dump_stack_lvl+0x61/0xa0
+[    5.419448]  print_deadlock_bug+0x4a6/0x650
+[    5.419483]  __lock_acquire+0x62b6/0x7f50
+[    5.419507]  lock_acquire+0x11b/0x390
+[    5.419654]  __mutex_lock+0xbc/0xcd0
+[    5.419741]  ucsi_init_work+0x1a78/0x2eb0
+[    5.419785]  ? worker_thread+0xf53/0x2bc0
+[    5.419819]  worker_thread+0xff4/0x2bc0
+[    5.419842]  kthread+0x2a7/0x330
+[    5.419863]  ? __pfx_worker_thread+0x10/0x10
+[    5.419896]  ? __pfx_kthread+0x10/0x10
+[    5.419916]  ret_from_fork+0x38/0x70
+[    5.419936]  ? __pfx_kthread+0x10/0x10
+[    5.419969]  ret_from_fork_asm+0x1b/0x30
+[    5.419991]  </TASK>
+[    5.420009] ---[ end trace 0000000000000000 ]---
+
+The problem is that all connector locks belong to the same
+lockdep lock class, so the following loop:
+
+       for (i = 0; i < ucsi->cap.num_connectors; i++)
+               ucsi_register_port(connector[i])
+                       mutex_lock(&connector[i]->lock)
+
+looks like a recursive acquire of the same mutex.  Put each connector
+lock into a dedicated lock class so that lockdep doesn't see it as a
+possible recursion.
+
+Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://patch.msgid.link/20260515060042.136083-1-senozhatsky@chromium.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 7aa7d4bf9d3f ("usb: typec: ucsi: Fix race condition and ordering in port unregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |    8 ++++++++
+ drivers/usb/typec/ucsi/ucsi.h |    1 +
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -1231,6 +1231,7 @@ static int ucsi_register_port(struct ucs
+       INIT_WORK(&con->work, ucsi_handle_connector_change);
+       init_completion(&con->complete);
+       mutex_init(&con->lock);
++      lockdep_set_class(&con->lock, &con->lock_key);
+       INIT_LIST_HEAD(&con->partner_tasks);
+       con->ucsi = ucsi;
+@@ -1479,6 +1480,9 @@ static int ucsi_init(struct ucsi *ucsi)
+               goto err_reset;
+       }
++      for (i = 0; i < ucsi->cap.num_connectors; i++)
++              lockdep_register_key(&connector[i].lock_key);
++
+       /* Register all connectors */
+       for (i = 0; i < ucsi->cap.num_connectors; i++) {
+               connector[i].num = i + 1;
+@@ -1508,6 +1512,9 @@ static int ucsi_init(struct ucsi *ucsi)
+       return 0;
+ err_unregister:
++      for (i = 0; i < ucsi->cap.num_connectors; i++)
++              lockdep_unregister_key(&connector[i].lock_key);
++
+       for (con = connector; con->port; con++) {
+               if (con->wq)
+                       destroy_workqueue(con->wq);
+@@ -1776,6 +1783,7 @@ void ucsi_unregister(struct ucsi *ucsi)
+               usb_power_delivery_unregister(ucsi->connector[i].pd);
+               ucsi->connector[i].pd = NULL;
+               typec_unregister_port(ucsi->connector[i].port);
++              lockdep_unregister_key(&ucsi->connector[i].lock_key);
+       }
+       kfree(ucsi->connector);
+--- a/drivers/usb/typec/ucsi/ucsi.h
++++ b/drivers/usb/typec/ucsi/ucsi.h
+@@ -350,6 +350,7 @@ struct ucsi_connector {
+       struct ucsi *ucsi;
+       struct mutex lock; /* port lock */
++      struct lock_class_key lock_key;
+       struct work_struct work;
+       struct completion complete;
+       struct workqueue_struct *wq;
diff --git a/queue-6.6/wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch b/queue-6.6/wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch
new file mode 100644 (file)
index 0000000..3dd838a
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-296839-greg=kroah.com@vger.kernel.org Thu Aug  6 15:56:28 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 09:50:25 -0400
+Subject: wifi: ath6kl: fix use-after-free in aggr_reset_state()
+To: stable@vger.kernel.org
+Cc: Daniel Hodges <git@danielhodges.dev>, Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>, Jeff Johnson <jeff.johnson@oss.qualcomm.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260806135025.603479-1-sashal@kernel.org>
+
+From: Daniel Hodges <git@danielhodges.dev>
+
+[ Upstream commit ba7debb4dd6427386862220e8335a53a4bfc235d ]
+
+The aggr_reset_state() function uses timer_delete() (non-synchronous)
+for the aggregation timer before proceeding to delete TID state and
+before the structure is freed by callers like aggr_module_destroy().
+
+If the timer callback (aggr_timeout) is executing when aggr_reset_state()
+is called, the callback will continue to access aggr_conn fields like
+rx_tid[] and stat[] which may be freed immediately after by
+kfree(aggr_info->aggr_conn) in aggr_module_destroy().
+
+Additionally, the timer callback can re-arm itself via mod_timer() while
+aggr_reset_state() is running, creating a more complex race condition.
+
+Use timer_delete_sync() instead to ensure any running timer callback
+has completed before returning.
+
+Fixes: bdcd81707973 ("Add ath6kl cleaned up driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Daniel Hodges <git@danielhodges.dev>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260206185207.30098-1-git@danielhodges.dev
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/ath/ath6kl/txrx.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath6kl/txrx.c
++++ b/drivers/net/wireless/ath/ath6kl/txrx.c
+@@ -1829,7 +1829,7 @@ void aggr_reset_state(struct aggr_info_c
+               return;
+       if (aggr_conn->timer_scheduled) {
+-              del_timer(&aggr_conn->timer);
++              timer_delete_sync(&aggr_conn->timer);
+               aggr_conn->timer_scheduled = false;
+       }
diff --git a/queue-6.6/wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch b/queue-6.6/wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch
new file mode 100644 (file)
index 0000000..29c3d23
--- /dev/null
@@ -0,0 +1,292 @@
+From stable+bounces-296847-greg=kroah.com@vger.kernel.org Thu Aug  6 16:01:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 10:01:39 -0400
+Subject: wifi: brcmfmac: drain bus_reset work on device removal
+To: stable@vger.kernel.org
+Cc: Fan Wu <fanwu01@zju.edu.cn>, Arend van Spriel <arend.vanspriel@broadcom.com>, Johannes Berg <johannes.berg@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260806140139.635428-1-sashal@kernel.org>
+
+From: Fan Wu <fanwu01@zju.edu.cn>
+
+[ Upstream commit 43b25879f004c98defa2776bedc6ca4763c51945 ]
+
+brcmf_fw_crashed() and the debugfs "reset" entry both schedule
+drvr->bus_reset, whose callback recovers drvr through container_of()
+and dereferences it.  The removal path frees drvr (brcmf_free ->
+wiphy_free) without draining the work, so a bus_reset callback pending
+or running during removal can outlive drvr.
+
+Cancellation cannot live in brcmf_detach() or brcmf_free(): the work
+callback reaches teardown through the bus .reset op (PCIe
+brcmf_pcie_reset -> brcmf_detach; SDIO brcmf_sdio_bus_reset ->
+brcmf_sdiod_remove -> brcmf_free), so cancelling there would wait for
+the running work and deadlock.
+
+Add a per-bus mutex (bus_reset_lock) and route all arming through
+brcmf_bus_schedule_reset(), which under the lock skips when the bus is
+marked removing.  Each bus remove entry calls
+brcmf_bus_cancel_reset_work(), which under the same lock sets removing
+and cancels the work.  Holding the mutex across cancel_work_sync() makes
+the set-removing + drain step atomic.  Every producer reaches the arming
+path from process context -- the PCIe firmware-halt notification runs in
+the threaded IRQ handler (brcmf_pcie_isr_thread) and the SDIO hostmail
+path runs from the data workqueue -- so the mutex is taken only in
+sleepable contexts.  Where applicable the remove entry first stops the
+firmware-crash producer: on PCIe mask the mailbox and synchronize_irq;
+on SDIO unregister the bus interrupt and cancel the data worker, which
+also reports firmware halts through brcmf_fw_crashed().  The mutex is
+initialized at bus allocation.  The SDIO suspend power-off path frees
+drvr through the same brcmf_sdiod_remove() and takes the same lock;
+resume re-allows the work only on a successful re-probe.
+
+Also guard brcmf_fw_crashed() against a NULL bus_if/drvr: it can fire
+before brcmf_attach() wires up drvr, and it dereferences drvr
+(bphy_err/brcmf_dev_coredump) before reaching the arming gate.
+
+The bus_reset work is shared across buses, so the drain is applied to
+every remove path: PCIe (the .reset op introduced by the Fixes commit),
+SDIO (arms the same work through brcmf_fw_crashed()), and USB (via the
+debugfs "reset" entry).  cancel_work_sync() drains a running or pending
+bus_reset work item before removal frees drvr, and patch 1/2 makes the
+scratch-buffer release safe when reset teardown has already released
+those DMA buffers.
+
+This patch fixes the lifetime of the bus_reset work item itself.  It does
+not attempt to address the separate, pre-existing lifetime of the
+asynchronous firmware completion started by the PCIe reset path.  That
+callback needs its own lifetime/ownership protocol and is being tracked
+separately.
+
+This issue was found by an in-house static analysis tool.
+
+Fixes: 4684997d9eea ("brcmfmac: reset PCIe bus on a firmware crash")
+Cc: stable@vger.kernel.org
+Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
+Assisted-by: Codex:gpt-5.6
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Link: https://patch.msgid.link/20260718024353.3147201-3-fanwu01@zju.edu.cn
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c |   13 +++
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h    |    6 +
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c   |   46 ++++++++++++--
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c   |    6 +
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c   |    6 +
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h   |    1 
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c    |    3 
+ 7 files changed, 77 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -1065,6 +1065,7 @@ static int brcmf_ops_sdio_probe(struct s
+       bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
+       if (!bus_if)
+               return -ENOMEM;
++      mutex_init(&bus_if->bus_reset_lock);
+       sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
+       if (!sdiodev) {
+               kfree(bus_if);
+@@ -1126,6 +1127,14 @@ static void brcmf_ops_sdio_remove(struct
+               if (func->num != 1)
+                       return;
++              /* Drain bus_reset before the shared brcmf_sdiod_remove()
++               * teardown, which the SDIO reset callback also reaches.  The
++               * data worker can arm bus_reset via brcmf_fw_crashed(); cancel
++               * it first.
++               */
++              brcmf_sdio_cancel_datawork(sdiodev->bus);
++              brcmf_bus_cancel_reset_work(bus_if);
++
+               /* only proceed with rest of cleanup if func 1 */
+               brcmf_sdiod_remove(sdiodev);
+@@ -1200,6 +1209,8 @@ static int brcmf_ops_sdio_suspend(struct
+       } else {
+               /* power will be cut so remove device, probe again in resume */
+               brcmf_sdiod_intr_unregister(sdiodev);
++              brcmf_sdio_cancel_datawork(sdiodev->bus);
++              brcmf_bus_cancel_reset_work(bus_if);
+               ret = brcmf_sdiod_remove(sdiodev);
+               if (ret)
+                       brcmf_err("Failed to remove device on suspend\n");
+@@ -1225,6 +1236,8 @@ static int brcmf_ops_sdio_resume(struct
+               ret = brcmf_sdiod_probe(sdiodev);
+               if (ret)
+                       brcmf_err("Failed to probe device on resume\n");
++              else
++                      brcmf_bus_allow_reset_work(bus_if);
+       } else {
+               if (sdiodev->wowl_enabled && sdiodev->settings->bus.sdio.oob_irq_supported)
+                       disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+@@ -9,6 +9,7 @@
+ #include <linux/kernel.h>
+ #include <linux/firmware.h>
+ #include <linux/device.h>
++#include <linux/mutex.h>
+ #include "debug.h"
+ /* IDs of the 6 default common rings of msgbuf protocol */
+@@ -179,6 +180,8 @@ struct brcmf_bus {
+       enum brcmf_fwvendor fwvid;
+       bool always_use_fws_queue;
+       bool wowl_supported;
++      bool removing;          /* device removal in progress; quiesce async work */
++      struct mutex bus_reset_lock;
+       const struct brcmf_bus_ops *ops;
+       struct brcmf_bus_msgbuf *msgbuf;
+@@ -186,6 +189,9 @@ struct brcmf_bus {
+       struct list_head list;
+ };
++void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if);
++void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if);
++
+ /*
+  * callback wrappers
+  */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1162,6 +1162,35 @@ static int brcmf_revinfo_read(struct seq
+       return 0;
+ }
++/*
++ * Serialize arming from debugfs reset and brcmf_fw_crashed() against
++ * teardown.  The remove path sets ->removing and drains the work while
++ * holding bus_reset_lock, so a racing armer is either drained or skips it.
++ */
++static void brcmf_bus_schedule_reset(struct brcmf_bus *bus_if)
++{
++      mutex_lock(&bus_if->bus_reset_lock);
++      if (bus_if->drvr && bus_if->drvr->bus_reset.func && !bus_if->removing)
++              schedule_work(&bus_if->drvr->bus_reset);
++      mutex_unlock(&bus_if->bus_reset_lock);
++}
++
++void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if)
++{
++      mutex_lock(&bus_if->bus_reset_lock);
++      bus_if->removing = true;
++      if (bus_if->drvr)
++              cancel_work_sync(&bus_if->drvr->bus_reset);
++      mutex_unlock(&bus_if->bus_reset_lock);
++}
++
++void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if)
++{
++      mutex_lock(&bus_if->bus_reset_lock);
++      bus_if->removing = false;
++      mutex_unlock(&bus_if->bus_reset_lock);
++}
++
+ static void brcmf_core_bus_reset(struct work_struct *work)
+ {
+       struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
+@@ -1182,7 +1211,7 @@ static ssize_t bus_reset_write(struct fi
+       if (value != 1)
+               return -EINVAL;
+-      schedule_work(&drvr->bus_reset);
++      brcmf_bus_schedule_reset(drvr->bus_if);
+       return count;
+ }
+@@ -1407,14 +1436,23 @@ void brcmf_dev_coredump(struct device *d
+ void brcmf_fw_crashed(struct device *dev)
+ {
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+-      struct brcmf_pub *drvr = bus_if->drvr;
++      struct brcmf_pub *drvr;
++
++      /* May fire before brcmf_attach() wires up drvr, or after removal
++       * has cleared it; guard the derefs below (and the arming gate in
++       * brcmf_bus_schedule_reset() already checks drvr/->removing).
++       */
++      if (!bus_if)
++              return;
++      drvr = bus_if->drvr;
++      if (!drvr)
++              return;
+       bphy_err(drvr, "Firmware has halted or crashed\n");
+       brcmf_dev_coredump(dev);
+-      if (drvr->bus_reset.func)
+-              schedule_work(&drvr->bus_reset);
++      brcmf_bus_schedule_reset(bus_if);
+ }
+ void brcmf_detach(struct device *dev)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -2467,6 +2467,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
+               ret = -ENOMEM;
+               goto fail;
+       }
++      mutex_init(&bus->bus_reset_lock);
+       bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL);
+       if (!bus->msgbuf) {
+               ret = -ENOMEM;
+@@ -2552,6 +2553,11 @@ brcmf_pcie_remove(struct pci_dev *pdev)
+       if (devinfo->ci)
+               brcmf_pcie_intr_disable(devinfo);
++      if (devinfo->irq_allocated)
++              synchronize_irq(pdev->irq);
++
++      brcmf_bus_cancel_reset_work(bus);
++
+       brcmf_detach(&pdev->dev);
+       brcmf_free(&pdev->dev);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -4550,6 +4550,12 @@ fail:
+       return NULL;
+ }
++void brcmf_sdio_cancel_datawork(struct brcmf_sdio *bus)
++{
++      if (bus)
++              cancel_work_sync(&bus->datawork);
++}
++
+ /* Detach and free everything */
+ void brcmf_sdio_remove(struct brcmf_sdio *bus)
+ {
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -361,6 +361,7 @@ int brcmf_sdiod_remove(struct brcmf_sdio
+ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
+ void brcmf_sdio_remove(struct brcmf_sdio *bus);
+ void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr);
++void brcmf_sdio_cancel_datawork(struct brcmf_sdio *bus);
+ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active);
+ void brcmf_sdio_wowl_config(struct device *dev, bool enabled);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -1261,6 +1261,7 @@ static int brcmf_usb_probe_cb(struct brc
+               ret = -ENOMEM;
+               goto fail;
+       }
++      mutex_init(&bus->bus_reset_lock);
+       bus->dev = dev;
+       bus_pub->bus = bus;
+@@ -1327,6 +1328,8 @@ brcmf_usb_disconnect_cb(struct brcmf_usb
+               return;
+       brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo);
++      brcmf_bus_cancel_reset_work(devinfo->bus_pub.bus);
++
+       brcmf_detach(devinfo->dev);
+       brcmf_free(devinfo->dev);
+       kfree(devinfo->bus_pub.bus);
diff --git a/queue-6.6/wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch b/queue-6.6/wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch
new file mode 100644 (file)
index 0000000..5eefd86
--- /dev/null
@@ -0,0 +1,130 @@
+From stable+bounces-296844-greg=kroah.com@vger.kernel.org Thu Aug  6 15:59:58 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 09:57:56 -0400
+Subject: wifi: brcmfmac: fix 43752 SDIO FWVID incorrectly labelled as Cypress (CYW)
+To: stable@vger.kernel.org
+Cc: Gokul Sivakumar <gokulkumar.sivakumar@infineon.com>, Arend van Spriel <arend.vanspriel@broadcom.com>, Johannes Berg <johannes.berg@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260806135757.628201-1-sashal@kernel.org>
+
+From: Gokul Sivakumar <gokulkumar.sivakumar@infineon.com>
+
+[ Upstream commit 74e2ef72bd4b25ce21c8f309d4f5b91b5df9ff5b ]
+
+Cypress(Infineon) is not the vendor for this 43752 SDIO WLAN chip, and so
+has not officially released any firmware binary for it. It is incorrect to
+maintain this WLAN chip with firmware vendor ID as "CYW". So relabel the
+chip's firmware Vendor ID as "WCC" as suggested by the maintainer.
+
+Fixes: d2587c57ffd8 ("brcmfmac: add 43752 SDIO ids and initialization")
+Fixes: f74f1ec22dc2 ("wifi: brcmfmac: add support for Cypress firmware api")
+Signed-off-by: Gokul Sivakumar <gokulkumar.sivakumar@infineon.com>
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Link: https://patch.msgid.link/20250724101136.6691-1-gokulkumar.sivakumar@infineon.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Stable-dep-of: 29ab31f3f271 ("wifi: brcmfmac: set F2 blocksize to 256 for BCM43752")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c     |    2 +-
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c       |    4 ++--
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c       |    8 ++++----
+ drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h |    2 +-
+ include/linux/mmc/sdio_ids.h                                  |    2 +-
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -991,9 +991,9 @@ static const struct sdio_device_id brcmf
+       BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354, WCC),
+       BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356, WCC),
+       BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359, WCC),
++      BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43752, WCC),
+       BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373, CYW),
+       BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012, CYW),
+-      BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, CYW),
+       BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359, CYW),
+       CYW_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW),
+       { /* end: all zeroes */ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+@@ -738,7 +738,7 @@ static u32 brcmf_chip_tcm_rambase(struct
+       case BRCM_CC_4364_CHIP_ID:
+       case CY_CC_4373_CHIP_ID:
+               return 0x160000;
+-      case CY_CC_43752_CHIP_ID:
++      case BRCM_CC_43752_CHIP_ID:
+       case BRCM_CC_4377_CHIP_ID:
+               return 0x170000;
+       case BRCM_CC_4378_CHIP_ID:
+@@ -1465,7 +1465,7 @@ bool brcmf_chip_sr_capable(struct brcmf_
+               reg = chip->ops->read32(chip->ctx, addr);
+               return (reg & CC_SR_CTL0_ENABLE_MASK) != 0;
+       case BRCM_CC_4359_CHIP_ID:
+-      case CY_CC_43752_CHIP_ID:
++      case BRCM_CC_43752_CHIP_ID:
+       case CY_CC_43012_CHIP_ID:
+               addr = CORE_CC_REG(pmu->base, retention_ctl);
+               reg = chip->ops->read32(chip->ctx, addr);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -654,10 +654,10 @@ static const struct brcmf_firmware_mappi
+       BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
+       BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
+       BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
++      BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752),
+       BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373),
+       BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012),
+       BRCMF_FW_ENTRY(CY_CC_43439_CHIP_ID, 0xFFFFFFFF, 43439),
+-      BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
+ };
+ #define TXCTL_CREDITS 2
+@@ -3425,8 +3425,8 @@ err:
+ static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus)
+ {
+-      if (bus->ci->chip == CY_CC_43012_CHIP_ID ||
+-          bus->ci->chip == CY_CC_43752_CHIP_ID)
++      if (bus->ci->chip == BRCM_CC_43752_CHIP_ID ||
++          bus->ci->chip == CY_CC_43012_CHIP_ID)
+               return true;
+       else
+               return false;
+@@ -4274,8 +4274,8 @@ static void brcmf_sdio_firmware_callback
+                                  bus->hostintmask, NULL);
+               switch (sdiod->func1->device) {
++              case SDIO_DEVICE_ID_BROADCOM_43752:
+               case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
+-              case SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752:
+                       brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
+                                 CY_4373_F2_WATERMARK);
+                       brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
+--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+@@ -52,13 +52,13 @@
+ #define BRCM_CC_43664_CHIP_ID         43664
+ #define BRCM_CC_43666_CHIP_ID         43666
+ #define BRCM_CC_4371_CHIP_ID          0x4371
++#define BRCM_CC_43752_CHIP_ID         43752
+ #define BRCM_CC_4377_CHIP_ID          0x4377
+ #define BRCM_CC_4378_CHIP_ID          0x4378
+ #define BRCM_CC_4387_CHIP_ID          0x4387
+ #define CY_CC_4373_CHIP_ID            0x4373
+ #define CY_CC_43012_CHIP_ID           43012
+ #define CY_CC_43439_CHIP_ID           43439
+-#define CY_CC_43752_CHIP_ID           43752
+ /* USB Device IDs */
+ #define BRCM_USB_43143_DEVICE_ID      0xbd1e
+--- a/include/linux/mmc/sdio_ids.h
++++ b/include/linux/mmc/sdio_ids.h
+@@ -76,7 +76,7 @@
+ #define SDIO_DEVICE_ID_BROADCOM_43430         0xa9a6
+ #define SDIO_DEVICE_ID_BROADCOM_43439         0xa9af
+ #define SDIO_DEVICE_ID_BROADCOM_43455         0xa9bf
+-#define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752 0xaae8
++#define SDIO_DEVICE_ID_BROADCOM_43752         0xaae8
+ #define SDIO_VENDOR_ID_CYPRESS                        0x04b4
+ #define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439 0xbd3d
diff --git a/queue-6.6/wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch b/queue-6.6/wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch
new file mode 100644 (file)
index 0000000..1cf9756
--- /dev/null
@@ -0,0 +1,59 @@
+From stable+bounces-296843-greg=kroah.com@vger.kernel.org Thu Aug  6 15:59:49 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  6 Aug 2026 09:57:57 -0400
+Subject: wifi: brcmfmac: set F2 blocksize to 256 for BCM43752
+To: stable@vger.kernel.org
+Cc: LiangCheng Wang <zaq14760@gmail.com>, Arend van Spriel <arend.vanspriel@broadcom.com>, Johannes Berg <johannes.berg@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260806135757.628201-2-sashal@kernel.org>
+
+From: LiangCheng Wang <zaq14760@gmail.com>
+
+[ Upstream commit 29ab31f3f27157648f2f7e6d5e1fd9792fdf0614 ]
+
+The BCM43752 is not reliable with the default 512-byte SDIO function 2
+block size: on an i.MX8MP board with an AMPAK AP6275S module at
+SDR104 / 200 MHz, an iperf TX stress test kills WLAN within seconds:
+
+  mmc_submit_one: CMD53 sg block write failed -84
+  brcmf_sdio_dpc: failed backplane access over SDIO, halting operation
+
+Commit d2587c57ffd8 ("brcmfmac: add 43752 SDIO ids and initialization")
+set up the 43752 like the 4373 for the F2 watermark but missed the F2
+block size, which the 4373 limits to 256 bytes. The vendor driver
+(bcmdhd) also programs a 256-byte F2 block size for this chip and runs
+the same hardware without errors.
+
+Group the 43752 with the 4373, matching the F2 watermark handling.
+With this change a 10-minute bidirectional iperf3 soak completes with
+zero SDIO errors at ~270 Mbit/s in each direction.
+
+Backporting note: kernels before v6.18 name this id
+SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, so on those trees the case
+label added by this patch must be adjusted to that name. Cherry-picking
+the rename commit 74e2ef72bd4b ("wifi: brcmfmac: fix 43752 SDIO FWVID
+incorrectly labelled as Cypress (CYW)") first is not a clean
+alternative: on trees before v6.17 its context collides with the 43751
+additions, and trees before v6.2 lack the FWVID framework it touches.
+
+Fixes: d2587c57ffd8 ("brcmfmac: add 43752 SDIO ids and initialization")
+Cc: stable@vger.kernel.org # see patch description, needs adjustments for <= 6.17
+Signed-off-by: LiangCheng Wang <zaq14760@gmail.com>
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Link: https://patch.msgid.link/20260715-b43752-f2-blksz-v2-1-f9be49856050@gmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -906,6 +906,7 @@ int brcmf_sdiod_probe(struct brcmf_sdio_
+               return ret;
+       }
+       switch (sdiodev->func2->device) {
++      case SDIO_DEVICE_ID_BROADCOM_43752:
+       case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
+               f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE;
+               break;