rust_binder: add `command`/`return` tracepoints

Add Rust Binder `command` and `return` tracepoint declarations and
wire them in where BC commands are parsed and BR return codes are
emitted to userspace.

Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Link: https://patch.msgid.link/20260317-rust-binder-trace-v3-6-6fae4fbcf637@sdhn.cc
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/android/binder/rust_binder_events.h b/drivers/android/binder/rust_binder_events.h
index 572a4bf..1a44678 100644
--- a/drivers/android/binder/rust_binder_events.h
+++ b/drivers/android/binder/rust_binder_events.h
@@ -145,6 +145,38 @@ TRACE_EVENT(binder_transaction_fd_recv,
 		  __entry->debug_id, __entry->fd, __entry->offset)
 );
 
+TRACE_EVENT(binder_command,
+	TP_PROTO(uint32_t cmd),
+	TP_ARGS(cmd),
+	TP_STRUCT__entry(
+		__field(uint32_t, cmd)
+	),
+	TP_fast_assign(
+		__entry->cmd = cmd;
+	),
+	TP_printk("cmd=0x%x %s",
+		  __entry->cmd,
+		  _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_command_strings) ?
+			  binder_command_strings[_IOC_NR(__entry->cmd)] :
+			  "unknown")
+);
+
+TRACE_EVENT(binder_return,
+	TP_PROTO(uint32_t cmd),
+	TP_ARGS(cmd),
+	TP_STRUCT__entry(
+		__field(uint32_t, cmd)
+	),
+	TP_fast_assign(
+		__entry->cmd = cmd;
+	),
+	TP_printk("cmd=0x%x %s",
+		  __entry->cmd,
+		  _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_return_strings) ?
+			  binder_return_strings[_IOC_NR(__entry->cmd)] :
+			  "unknown")
+);
+
 #endif /* _RUST_BINDER_TRACE_H */
 
 /* This part must be outside protection */
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 76f01a3..8646930 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -118,6 +118,7 @@ fn new(writer: UserSliceWriter, thread: &'a Thread) -> Self {
     /// Write a return code back to user space.
     /// Should be a `BR_` constant from [`defs`] e.g. [`defs::BR_TRANSACTION_COMPLETE`].
     fn write_code(&mut self, code: u32) -> Result {
+        crate::trace::trace_return(code);
         stats::GLOBAL_STATS.inc_br(code);
         self.thread.process.stats.inc_br(code);
         self.writer.write(&code)
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 1feac87..97d5f31 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -1370,6 +1370,7 @@ fn write(self: &Arc<Self>, req: &mut BinderWriteRead) -> Result {
         while reader.len() >= size_of::<u32>() && self.inner.lock().return_work.is_unused() {
             let before = reader.len();
             let cmd = reader.read::<u32>()?;
+            crate::trace::trace_command(cmd);
             GLOBAL_STATS.inc_bc(cmd);
             self.process.stats.inc_bc(cmd);
             match cmd {
diff --git a/drivers/android/binder/trace.rs b/drivers/android/binder/trace.rs
index c6f39d8..5539672 100644
--- a/drivers/android/binder/trace.rs
+++ b/drivers/android/binder/trace.rs
@@ -20,6 +20,8 @@
     unsafe fn binder_transaction_received(t: rust_binder_transaction);
     unsafe fn binder_transaction_fd_send(t_debug_id: c_int, fd: c_int, offset: usize);
     unsafe fn binder_transaction_fd_recv(t_debug_id: c_int, fd: c_int, offset: usize);
+    unsafe fn binder_command(cmd: u32);
+    unsafe fn binder_return(ret: u32);
 }
 
 #[inline]
@@ -90,3 +92,14 @@ pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usiz
     // SAFETY: This function is always safe to call.
     unsafe { binder_transaction_fd_recv(t_debug_id as c_int, fd as c_int, offset) }
 }
+
+#[inline]
+pub(crate) fn trace_command(cmd: u32) {
+    // SAFETY: This function is always safe to call.
+    unsafe { binder_command(cmd) }
+}
+#[inline]
+pub(crate) fn trace_return(ret: u32) {
+    // SAFETY: This function is always safe to call.
+    unsafe { binder_return(ret) }
+}