diff options
| author | Danilo Krummrich <dakr@kernel.org> | 2026-09-29 20:59:30 +0200 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-10-10 22:15:45 +0200 |
| commit | 700eed1364e8a5ec4318d457cf700611decdb175 (patch) | |
| tree | 177a3b320b1f6cc84b5216c6631787547e54a5b4 /drivers/gpu | |
| parent | 3e3404c52370595e37eb5b942df169884f38a124 (diff) | |
| download | linux-700eed1364e8a5ec4318d457cf700611decdb175.tar.gz linux-700eed1364e8a5ec4318d457cf700611decdb175.zip | |
rust: drm: Return impl PinInit from drm::Registration::new()
Convert drm::Registration to return an impl PinInit<Self, Error> rather
than creating a separate allocation. This removes an otherwise
unnecessary allocation.
Update both in-tree callers (nova, tyr) to construct their bus device
private data using try_pin_init!().
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20260929190024.2248099-1-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/nova/driver.rs | 27 | ||||
| -rw-r--r-- | drivers/gpu/drm/tyr/driver.rs | 138 |
2 files changed, 86 insertions, 79 deletions
diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index 851d50b4dd15..7a51d49feb1f 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -25,10 +25,11 @@ use nova_core::api::{ pub(crate) struct NovaDriver; +#[pin_data] pub(crate) struct Nova<'bound> { - #[expect(unused)] drm: ARef<drm::Device<NovaDriver>>, - _reg: drm::Registration<'bound, NovaDriver>, + #[pin] + reg: drm::Registration<'bound, NovaDriver>, } /// DRM registration data, accessible from ioctl handlers via the registration guard. @@ -68,17 +69,19 @@ impl auxiliary::Driver for NovaDriver { adev: &'bound auxiliary::Device<Core<'_>>, _info: &'bound Self::IdInfo, ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound { - let drm = drm::UnregisteredDevice::<Self>::new(adev, Ok(()))?; - let reg_data = DrmRegData { - api: NovaCoreApi::of(adev)?, - }; - // SAFETY: `reg` is stored in `Nova` and dropped when the driver is unbound; it is - // never forgotten. - let reg = unsafe { drm::Registration::new(adev.as_ref(), drm, reg_data, 0)? }; - - Ok(Nova { + try_pin_init!(Self::Data { + reg <- { + let drm = drm::UnregisteredDevice::<Self>::new(adev, Ok(()))?; + + let reg_data = DrmRegData { + api: NovaCoreApi::of(adev)?, + }; + + // SAFETY: `reg` is stored in `Self::Data` and dropped when the driver is unbound; + // it is never forgotten. + unsafe { drm::Registration::new(adev.as_ref(), drm, reg_data, 0) } + }, drm: reg.device().into(), - _reg: reg, }) } } diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index 730b84e37a54..6e1008290b5f 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -57,6 +57,7 @@ pub(crate) struct TyrPlatformDriver; #[pin_data(PinnedDrop)] pub(crate) struct TyrPlatformDriverData<'bound> { + #[pin] _reg: drm::Registration<'bound, TyrDrmDriver>, } @@ -117,73 +118,76 @@ impl platform::Driver for TyrPlatformDriver { pdev: &'bound platform::Device<Core<'_>>, _info: Option<&'bound Self::IdInfo>, ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound { - let core_clk = Clk::get(pdev.as_ref(), Some(c"core"))?; - let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c"stacks"))?; - let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c"coregroup"))?; - - core_clk.prepare_enable()?; - stacks_clk.prepare_enable()?; - coregroup_clk.prepare_enable()?; - - let mali_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"mali")?; - let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"sram")?; - - let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; - - let iomem = Arc::new(request.iomap_sized::<SZ_2M>()?, GFP_KERNEL)?; - - issue_soft_reset(pdev.as_ref(), &iomem)?; - gpu::l2_power_on(pdev.as_ref(), &iomem)?; - - let gpu_info = GpuInfo::new(&iomem); - gpu_info.log(pdev.as_ref()); - - let pa_bits = MMU_FEATURES::from_raw(gpu_info.mmu_features) - .pa_bits() - .get(); - // SAFETY: No concurrent DMA allocations or mappings can be made because - // the device is still being probed and therefore isn't being used by - // other threads of execution. - unsafe { pdev.dma_set_mask_and_coherent(DmaMask::try_new(pa_bits)?)? }; - - let unreg_dev = drm::UnregisteredDevice::<TyrDrmDriver>::new(pdev, Ok(()))?; - - let mmu = Mmu::new(pdev.as_ref(), iomem.as_arc_borrow(), &gpu_info)?; - - let firmware = Firmware::new( - pdev.as_ref(), - iomem.clone(), - &unreg_dev, - mmu.as_arc_borrow(), - &gpu_info, - )?; - - firmware.boot()?; - - let reg_data = pin_init!(TyrDrmRegistrationData { - pdev, - fw: firmware, - clks <- new_mutex!(Clocks { - core: core_clk, - stacks: stacks_clk, - coregroup: coregroup_clk, - }), - regulators <- new_mutex!(Regulators { - _mali: mali_regulator, - _sram: sram_regulator, - }), - iomem, - gpu_info, - }); - - // SAFETY: `reg` is stored in `TyrPlatformDriverData` and dropped when the driver is - // unbound; it is never forgotten. - let reg = unsafe { drm::Registration::new(pdev.as_ref(), unreg_dev, reg_data, 0)? }; - - let driver = TyrPlatformDriverData { _reg: reg }; - - dev_dbg!(pdev, "Tyr initialized correctly."); - Ok(driver) + pin_init::pin_init_scope(move || { + let core_clk = Clk::get(pdev.as_ref(), Some(c"core"))?; + let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c"stacks"))?; + let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c"coregroup"))?; + + core_clk.prepare_enable()?; + stacks_clk.prepare_enable()?; + coregroup_clk.prepare_enable()?; + + let mali_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"mali")?; + let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"sram")?; + + let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; + + let iomem = Arc::new(request.iomap_sized::<SZ_2M>()?, GFP_KERNEL)?; + + issue_soft_reset(pdev.as_ref(), &iomem)?; + gpu::l2_power_on(pdev.as_ref(), &iomem)?; + + let gpu_info = GpuInfo::new(&iomem); + gpu_info.log(pdev.as_ref()); + + let pa_bits = MMU_FEATURES::from_raw(gpu_info.mmu_features) + .pa_bits() + .get(); + // SAFETY: No concurrent DMA allocations or mappings can be made because + // the device is still being probed and therefore isn't being used by + // other threads of execution. + unsafe { pdev.dma_set_mask_and_coherent(DmaMask::try_new(pa_bits)?)? }; + + let unreg_dev = drm::UnregisteredDevice::<TyrDrmDriver>::new(pdev, Ok(()))?; + + let mmu = Mmu::new(pdev.as_ref(), iomem.as_arc_borrow(), &gpu_info)?; + + let firmware = Firmware::new( + pdev.as_ref(), + iomem.clone(), + &unreg_dev, + mmu.as_arc_borrow(), + &gpu_info, + )?; + + firmware.boot()?; + + Ok(try_pin_init!(TyrPlatformDriverData { + // SAFETY: `_reg` is stored in `TyrPlatformDriverData` and dropped when the + // driver is unbound; it is never forgotten. + _reg <- unsafe { drm::Registration::new( + pdev.as_ref(), + unreg_dev, + pin_init!(TyrDrmRegistrationData { + pdev, + fw: firmware, + clks <- new_mutex!(Clocks { + core: core_clk, + stacks: stacks_clk, + coregroup: coregroup_clk, + }), + regulators <- new_mutex!(Regulators { + _mali: mali_regulator, + _sram: sram_regulator, + }), + iomem, + gpu_info, + }), + 0, + )}, + _: { dev_dbg!(pdev, "Tyr initialized correctly.") }, + })) + }) } } |
