Refresh redox-drm and AMD GPU driver

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-17 00:03:28 +01:00
parent 6b887e9166
commit 00cda85edd
13 changed files with 737 additions and 399 deletions
@@ -44,8 +44,11 @@ unsafe extern "C" {
fn ffi_redox_pci_set_device_info(
vendor: u16,
device: u16,
bus_number: u8,
dev_number: u8,
func_number: u8,
revision: u8,
irq: u8,
irq: u32,
bar0_addr: u64,
bar0_size: u64,
bar2_addr: u64,
@@ -105,6 +108,9 @@ fn amdgpu_dc_cleanup() {
pub fn set_pci_device_info(
vendor: u16,
device: u16,
bus_number: u8,
dev_number: u8,
func_number: u8,
revision: u8,
irq: u32,
bar0_addr: u64,
@@ -115,11 +121,31 @@ pub fn set_pci_device_info(
#[cfg(not(no_amdgpu_c))]
unsafe {
ffi_redox_pci_set_device_info(
vendor, device, revision, irq as u8, bar0_addr, bar0_size, bar2_addr, bar2_size,
vendor,
device,
bus_number,
dev_number,
func_number,
revision,
irq,
bar0_addr,
bar0_size,
bar2_addr,
bar2_size,
);
}
let _ = (
vendor, device, revision, irq, bar0_addr, bar0_size, bar2_addr, bar2_size,
vendor,
device,
bus_number,
dev_number,
func_number,
revision,
irq,
bar0_addr,
bar0_size,
bar2_addr,
bar2_size,
);
}
@@ -102,6 +102,9 @@ impl AmdDriver {
display::set_pci_device_info(
info.vendor_id,
info.device_id,
info.location.bus,
info.location.device,
info.location.function,
info.revision,
info.irq.unwrap_or(0),
bar0.addr,
@@ -522,22 +525,6 @@ impl GpuDriver for AmdDriver {
Ok(gem.object(handle)?.size)
}
fn gem_export_dmafd(&self, handle: GemHandle) -> Result<i32> {
let mut gem = self
.gem
.lock()
.map_err(|_| DriverError::Buffer("GEM manager poisoned".to_string()))?;
gem.export_dmafd(handle)
}
fn gem_import_dmafd(&self, fd: i32) -> Result<GemHandle> {
let gem = self
.gem
.lock()
.map_err(|_| DriverError::Buffer("GEM manager poisoned".to_string()))?;
gem.import_dmafd(fd)
}
fn get_edid(&self, connector_id: u32) -> Vec<u8> {
match self.connectors.lock() {
Ok(connectors) => connectors
@@ -443,27 +443,6 @@ impl GpuDriver for IntelDriver {
Ok(gem.object(handle)?.size)
}
fn gem_export_dmafd(&self, handle: GemHandle) -> Result<i32> {
let mut gem = self
.gem
.lock()
.map_err(|_| DriverError::Buffer("Intel GEM manager poisoned".into()))?;
gem.export_dmafd(handle)
}
fn gem_import_dmafd(&self, fd: i32) -> Result<GemHandle> {
let handle = {
let gem = self
.gem
.lock()
.map_err(|_| DriverError::Buffer("Intel GEM manager poisoned".into()))?;
gem.import_dmafd(fd)?
};
let _ = self.ensure_gem_gpu_mapping(handle)?;
Ok(handle)
}
fn get_edid(&self, connector_id: u32) -> Vec<u8> {
match self.connectors.lock() {
Ok(connectors) => connectors
@@ -2,7 +2,8 @@ use std::io::{Read, Write};
use log::{info, warn};
use redox_driver_sys::irq::{IrqHandle, MsixTable, MsixVector};
use redox_driver_sys::pci::{PciDevice, PciDeviceInfo, PCI_CAP_ID_MSIX};
use redox_driver_sys::pci::{PciDevice, PciDeviceInfo, PCI_CAP_ID_MSI, PCI_CAP_ID_MSIX};
use redox_driver_sys::quirks::PciQuirkFlags;
use crate::driver::{DriverError, Result};
@@ -12,6 +13,10 @@ pub enum InterruptHandle {
table: MsixTable,
cap_offset: u8,
},
Msi {
handle: IrqHandle,
irq: u32,
},
Legacy {
handle: IrqHandle,
irq: u32,
@@ -20,8 +25,35 @@ pub enum InterruptHandle {
impl InterruptHandle {
pub fn setup(device_info: &PciDeviceInfo, pci_device: &mut PciDevice) -> Result<Self> {
if let Ok(Some(handle)) = Self::try_msix(device_info, pci_device) {
return Ok(handle);
let quirks = device_info.quirks();
if !quirks.contains(PciQuirkFlags::NO_MSIX) {
if let Ok(Some(handle)) = Self::try_msix(device_info, pci_device) {
return Ok(handle);
}
} else {
info!(
"redox-drm: skipping MSI-X for {} (NO_MSIX quirk)",
device_info.location
);
}
if !quirks.contains(PciQuirkFlags::NO_MSI) {
if let Ok(Some(handle)) = Self::try_msi(device_info, pci_device) {
return Ok(handle);
}
} else {
info!(
"redox-drm: skipping MSI for {} (NO_MSI quirk)",
device_info.location
);
}
if quirks.contains(PciQuirkFlags::FORCE_LEGACY_IRQ) {
info!(
"redox-drm: forcing legacy IRQ for {} (FORCE_LEGACY_IRQ quirk)",
device_info.location
);
}
Self::try_legacy(device_info)
@@ -89,6 +121,35 @@ impl InterruptHandle {
}))
}
fn try_msi(device_info: &PciDeviceInfo, _pci_device: &mut PciDevice) -> Result<Option<Self>> {
let msi_cap = match device_info.find_capability(PCI_CAP_ID_MSI) {
Some(cap) => cap,
None => return Ok(None),
};
let irq = device_info.irq.ok_or_else(|| {
DriverError::Io(format!("no IRQ for MSI on {}", device_info.location))
})?;
let handle = match IrqHandle::request(irq) {
Ok(h) => h,
Err(e) => {
warn!(
"redox-drm: MSI IRQ request failed for {}: {e}",
device_info.location
);
return Ok(None);
}
};
info!(
"redox-drm: MSI enabled for {} cap_offset={:#x} irq {}",
device_info.location, msi_cap.offset, irq
);
Ok(Some(InterruptHandle::Msi { handle, irq }))
}
fn try_legacy(device_info: &PciDeviceInfo) -> Result<Self> {
let irq = device_info
.irq
@@ -114,7 +175,7 @@ impl InterruptHandle {
Err(e) => Err(DriverError::Io(e.to_string())),
}
}
InterruptHandle::Legacy { handle, .. } => handle
InterruptHandle::Msi { handle, .. } | InterruptHandle::Legacy { handle, .. } => handle
.try_wait()
.map(|ev| ev.is_some())
.map_err(|e| DriverError::Io(e.to_string())),
@@ -134,7 +195,7 @@ impl InterruptHandle {
.write_all(&buf)
.map_err(|e| DriverError::Io(e.to_string()))
}
InterruptHandle::Legacy { handle, .. } => {
InterruptHandle::Msi { handle, .. } | InterruptHandle::Legacy { handle, .. } => {
let mut buf = [0u8; 8];
let _ = handle.wait().map_err(|e| DriverError::Io(e.to_string()))?;
Ok(())
@@ -145,7 +206,7 @@ impl InterruptHandle {
pub fn irq(&self) -> u32 {
match self {
InterruptHandle::Msix { vector, .. } => vector.irq,
InterruptHandle::Legacy { irq, .. } => *irq,
InterruptHandle::Msi { irq, .. } | InterruptHandle::Legacy { irq, .. } => *irq,
}
}
@@ -5,7 +5,9 @@ pub mod interrupt;
use std::collections::HashMap;
use std::sync::Arc;
use log::info;
use redox_driver_sys::pci::{PciDevice, PciDeviceInfo, PCI_VENDOR_ID_AMD, PCI_VENDOR_ID_INTEL};
use redox_driver_sys::quirks::PciQuirkFlags;
use crate::driver::{DriverError, GpuDriver, Result};
@@ -26,6 +28,21 @@ impl DriverRegistry {
info
};
let quirks = full.quirks();
if !quirks.is_empty() {
info!(
"redox-drm: quirks for {:#06x}:{:#06x}: {:?}",
full.vendor_id, full.device_id, quirks
);
}
if quirks.contains(PciQuirkFlags::DISABLE_ACCEL) {
return Err(DriverError::Pci(format!(
"device {:#06x}:{:#06x} at {} has DISABLE_ACCEL quirk — skipping probe",
full.vendor_id, full.device_id, full.location
)));
}
match full.vendor_id {
PCI_VENDOR_ID_AMD => {
let driver = amd::AmdDriver::new(full, firmware)?;