提交 aef3a777 编写于 作者: 李弘宇's avatar 李弘宇

rust: driver: add cavium_rng_rust driver

openeuler inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5TUIJ
CVE: NA

----------------------------------------------------------------------
Signed-off-by: 李弘宇's avatarLi Hongyu <543306408@qq.com>
上级 63bc3fc5
...@@ -438,6 +438,18 @@ config HW_RANDOM_CAVIUM ...@@ -438,6 +438,18 @@ config HW_RANDOM_CAVIUM
If unsure, say Y. If unsure, say Y.
config HW_RANDOM_CAVIUM_RUST
tristate "Rust implementation of Cavium ThunderX Random Number Generator"
depends on RUST && HW_RANDOM && PCI && ARCH_THUNDER
help
This driver provides alternative Rust-based kernel-side support
for the Random Number Generator hardware found on Cavium SoCs.
To compile this driver as a module, choose M here: the
module will be called cavium_rng_rust.
If unsure, say N.
config HW_RANDOM_MTK config HW_RANDOM_MTK
tristate "Mediatek Random Number Generator support" tristate "Mediatek Random Number Generator support"
depends on HW_RANDOM depends on HW_RANDOM
......
...@@ -39,6 +39,7 @@ obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o ...@@ -39,6 +39,7 @@ obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o
obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
obj-$(CONFIG_HW_RANDOM_CAVIUM_RUST) += cavium_rng_rust.o
obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o
obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o
......
// SPDX-License-Identifier: GPL-2.0
//! Broadcom CAVIUM Random Number Generator support.
use kernel::{
bindings, define_pci_id_table, device, file, file::File, io_buffer::IoBufferWriter,
io_mem::IoMem, miscdev, module_pci_driver, pci, prelude::*, sync::Ref,
};
module_pci_driver! {
type: RngDriver,
name: b"cavium_rng_rust",
author: b"Rust for Linux Contributors",
description: b"Cavium Random Number Generator (RNG) driver",
license: b"GPL v2",
}
const THUNDERX_RNM_ENT_EN: u64 = 0x1;
const THUNDERX_RNM_RNG_EN: u64 = 0x2;
const CAVIUM_SIZE: usize = 0x1000;
struct RngDevice;
impl file::Operations for RngDevice {
kernel::declare_file_operations!();
fn open(_open_data: &(), _file: &File) -> Result {
Ok(())
}
fn read(_: (), _: &File, data: &mut impl IoBufferWriter, offset: u64) -> Result<usize> {
// Succeed if the caller doesn't provide a buffer or if not at the start.
if data.is_empty() || offset != 0 {
return Ok(0);
}
data.write(&0_u32)?;
Ok(4)
}
}
struct CAVIUMResources {
base: IoMem<CAVIUM_SIZE>,
}
struct CAVIUMData {
dev: device::Device,
}
type DeviceData = device::Data<miscdev::Registration<RngDevice>, CAVIUMResources, CAVIUMData>;
struct RngDriver;
impl pci::Driver for RngDriver {
type Data = Ref<DeviceData>;
define_pci_id_table! {u32, [
(pci::DeviceId::new(bindings::PCI_VENDOR_ID_CAVIUM, 0xa018), None),
]}
fn probe(dev: &mut pci::Device, _id_info: Option<&Self::IdInfo>) -> Result<Self::Data> {
let res = dev.take_resource().ok_or(ENXIO)?;
let res = CAVIUMResources {
// SAFETY: This device doesn't support DMA.
base: unsafe { IoMem::try_new(res)? },
};
res.base
.writeq(THUNDERX_RNM_ENT_EN | THUNDERX_RNM_RNG_EN, 0);
let ret = dev.pci_enable_sriov(1);
match ret {
Ok(_o) => (),
Err(_e) => {
dev_err!(dev, "Error initializing RNG virtual function.\n",);
res.base.writeq(0, 0);
return Err(_e);
}
}
let cdata = CAVIUMData {
dev: device::Device::from_dev(dev),
};
let mut data = kernel::new_device_data!(
miscdev::Registration::new(),
res,
cdata,
"CAVIUM::Registrations"
)?;
let data = Ref::<DeviceData>::from(data);
data.registrations()
.ok_or(ENXIO)?
.as_pinned_mut()
.register(fmt!("rust_cavium"), ())?;
Ok(data.into())
}
}
...@@ -107,11 +107,7 @@ unsafe impl AlwaysRefCounted for SkBuff { ...@@ -107,11 +107,7 @@ unsafe impl AlwaysRefCounted for SkBuff {
unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) { unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
// SAFETY: The safety requirements guarantee that the refcount is nonzero. // SAFETY: The safety requirements guarantee that the refcount is nonzero.
unsafe { unsafe { bindings::__kfree_skb(obj.cast().as_ptr()) };
bindings::__kfree_skb(
obj.cast().as_ptr()
)
};
} }
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
use crate::{ use crate::{
bindings, c_types, device, driver, bindings, c_types, device, driver,
error::{from_kernel_result, Result}, error::{from_kernel_result, Result},
io_mem::Resource,
str::CStr, str::CStr,
to_result, to_result,
types::PointerWrapper, types::PointerWrapper,
...@@ -165,7 +166,7 @@ unsafe impl const driver::RawDeviceId for DeviceId { ...@@ -165,7 +166,7 @@ unsafe impl const driver::RawDeviceId for DeviceId {
macro_rules! define_pci_id_table { macro_rules! define_pci_id_table {
($data_type:ty, $($t:tt)*) => { ($data_type:ty, $($t:tt)*) => {
type IdInfo = $data_type; type IdInfo = $data_type;
const ID_TABLE: $crate::driver::IdTable<'static, $crate::pci::DeviceId, $data_type> = { const PCI_ID_TABLE: $crate::driver::IdTable<'static, $crate::pci::DeviceId, $data_type> = {
$crate::define_id_array!(ARRAY, $crate::pci::DeviceId, $data_type, $($t)* ); $crate::define_id_array!(ARRAY, $crate::pci::DeviceId, $data_type, $($t)* );
ARRAY.as_table() ARRAY.as_table()
}; };
...@@ -199,7 +200,7 @@ pub trait Driver { ...@@ -199,7 +200,7 @@ pub trait Driver {
/// ///
/// Called when a platform device is removed. /// Called when a platform device is removed.
/// Implementers should prepare the device for complete removal here. /// Implementers should prepare the device for complete removal here.
fn remove(_data: &Self::Data); fn remove(_data: &Self::Data) {}
} }
/// A PCI device. /// A PCI device.
...@@ -209,11 +210,43 @@ pub trait Driver { ...@@ -209,11 +210,43 @@ pub trait Driver {
/// The field `ptr` is non-null and valid for the lifetime of the object. /// The field `ptr` is non-null and valid for the lifetime of the object.
pub struct Device { pub struct Device {
ptr: *mut bindings::pci_dev, ptr: *mut bindings::pci_dev,
res: Option<Resource>,
} }
impl Device { impl Device {
/// Creates a new device from the given pointer.
///
/// # Safety
///
/// `ptr` must be non-null and valid. It must remain valid for the lifetime of the returned
/// instance.
unsafe fn from_ptr(ptr: *mut bindings::pci_dev) -> Self { unsafe fn from_ptr(ptr: *mut bindings::pci_dev) -> Self {
Self { ptr } // SAFETY: The safety requirements of the function ensure that `ptr` is valid.
let dev = unsafe { &mut *ptr };
// INVARIANT: The safety requirements of the function ensure the lifetime invariant.
Self {
ptr,
res: Resource::new(dev.resource[0].start, dev.resource[0].end),
}
}
/// Returns the io mem resource associated with the device, if there is one.
///
/// Ownership of the resource is transferred to the caller, so subsequent calls to this
/// function will return [`None`].
pub fn take_resource(&mut self) -> Option<Resource> {
self.res.take()
}
pub fn pci_enable_sriov(&self, nr_virtfn: i32) -> Result {
to_result(||
// SAFETY: The existence of the shared references mean `self.0`is valid.
unsafe{bindings::pci_enable_sriov(self.ptr, nr_virtfn)})
}
fn pci_disable_sriov(&self) {
// SAFETY: The existence of the shared references mean `self.0`is valid.
unsafe { bindings::pci_disable_sriov(self.ptr) }
} }
} }
...@@ -223,3 +256,35 @@ unsafe impl device::RawDevice for Device { ...@@ -223,3 +256,35 @@ unsafe impl device::RawDevice for Device {
unsafe { &mut (*self.ptr).dev } unsafe { &mut (*self.ptr).dev }
} }
} }
/// Declares a kernel module that exposes a single pci driver.
///
/// # Examples
///
/// ```ignore
/// # use kernel::{pci, define_pci_id_table, module_pci_driver};
/// #
/// struct MyDriver;
/// impl pci::Driver for MyDriver {
/// // [...]
/// # fn probe(_dev: &mut pci::Device, _id_info: Option<&Self::IdInfo>) -> Result {
/// # Ok(())
/// # }
/// # define_pci_id_table! {u32, [
/// # (pci::DeviceId::new(0x177d, 0xa018), None),
/// # ]}
/// }
///
/// module_pci_driver! {
/// type: MyDriver,
/// name: b"module_name",
/// author: b"Author name",
/// license: b"GPL",
/// }
/// ```
#[macro_export]
macro_rules! module_pci_driver {
($($f:tt)*) => {
$crate::module_driver!(<T>, $crate::pci::Adapter<T>, { $($f)* });
};
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册