Require a borrowed `DeviceEnableGuard` for the same device before enabling
bus-mastering. Check device identity so a guard for another device cannot
satisfy this requirement.

Keep `set_master()` on `Device<Core>` to retain callback synchronization:
the guard is shareable, while `pci_set_master()` modifies device state
without locking. Convert nova-core to pass its enable guard.

Link: 
https://lore.kernel.org/rust-for-linux/[email protected]
Suggested-by: Danilo Krummrich <[email protected]>
Signed-off-by: Maurice Hieronymus <[email protected]>
---
 drivers/gpu/nova-core/driver.rs |  2 +-
 rust/kernel/pci.rs              | 12 ++++++++++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs
index f0aebfe705ba..94f207c6078d 100644
--- a/drivers/gpu/nova-core/driver.rs
+++ b/drivers/gpu/nova-core/driver.rs
@@ -107,7 +107,7 @@ fn probe<'bound>(
         try_pin_init!(NovaCore {
             _enable: {
                 let enable = pdev.enable_device()?;
-                pdev.set_master();
+                pdev.set_master(&enable)?;
                 enable
             },
 
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 75efd5c5ee97..20f45ca960cd 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -516,10 +516,18 @@ pub fn enable_device(&self) -> 
Result<DeviceEnableGuard<'_>> {
     }
 
     /// Enable bus-mastering for this device.
+    ///
+    /// Returns `EINVAL` if `enable` belongs to another device.
     #[inline]
-    pub fn set_master(&self) {
-        // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid 
`struct pci_dev`.
+    pub fn set_master(&self, enable: &DeviceEnableGuard<'_>) -> Result {
+        if self.as_raw() != enable.dev.as_raw() {
+            return Err(EINVAL);
+        }
+
+        // SAFETY: `self` is a valid device in core context, and `enable`
+        // keeps this device enabled for the duration of the call.
         unsafe { bindings::pci_set_master(self.as_raw()) };
+        Ok(())
     }
 }
 

-- 
2.54.0

Reply via email to