1edd86506SAndreas Hindborg // SPDX-License-Identifier: GPL-2.0 2edd86506SAndreas Hindborg 3edd86506SAndreas Hindborg //! This is a Rust implementation of the C null block driver. 4d969d504SAndreas Hindborg 5d969d504SAndreas Hindborg mod configfs; 6edd86506SAndreas Hindborg 7*34585dc6SAndreas Hindborg use configfs::IRQMode; 8edd86506SAndreas Hindborg use kernel::{ 9d969d504SAndreas Hindborg block::{ 10d969d504SAndreas Hindborg self, 11d969d504SAndreas Hindborg mq::{ 12edd86506SAndreas Hindborg self, 13edd86506SAndreas Hindborg gen_disk::{self, GenDisk}, 14edd86506SAndreas Hindborg Operations, TagSet, 15edd86506SAndreas Hindborg }, 16d969d504SAndreas Hindborg }, 17edd86506SAndreas Hindborg error::Result, 18d969d504SAndreas Hindborg pr_info, 19edd86506SAndreas Hindborg prelude::*, 20d969d504SAndreas Hindborg sync::Arc, 21edd86506SAndreas Hindborg types::ARef, 22edd86506SAndreas Hindborg }; 23d969d504SAndreas Hindborg use pin_init::PinInit; 24edd86506SAndreas Hindborg 25edd86506SAndreas Hindborg module! { 26edd86506SAndreas Hindborg type: NullBlkModule, 27edd86506SAndreas Hindborg name: "rnull_mod", 28edd86506SAndreas Hindborg authors: ["Andreas Hindborg"], 29edd86506SAndreas Hindborg description: "Rust implementation of the C null block driver", 30edd86506SAndreas Hindborg license: "GPL v2", 31edd86506SAndreas Hindborg } 32edd86506SAndreas Hindborg 33edd86506SAndreas Hindborg #[pin_data] 34edd86506SAndreas Hindborg struct NullBlkModule { 35edd86506SAndreas Hindborg #[pin] 36d969d504SAndreas Hindborg configfs_subsystem: kernel::configfs::Subsystem<configfs::Config>, 37edd86506SAndreas Hindborg } 38edd86506SAndreas Hindborg 39edd86506SAndreas Hindborg impl kernel::InPlaceModule for NullBlkModule { 40edd86506SAndreas Hindborg fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> { 41edd86506SAndreas Hindborg pr_info!("Rust null_blk loaded\n"); 42edd86506SAndreas Hindborg 43edd86506SAndreas Hindborg try_pin_init!(Self { 44d969d504SAndreas Hindborg configfs_subsystem <- configfs::subsystem(), 45edd86506SAndreas Hindborg }) 46edd86506SAndreas Hindborg } 47edd86506SAndreas Hindborg } 48edd86506SAndreas Hindborg 49edd86506SAndreas Hindborg struct NullBlkDevice; 50edd86506SAndreas Hindborg 51d969d504SAndreas Hindborg impl NullBlkDevice { 52d969d504SAndreas Hindborg fn new( 53d969d504SAndreas Hindborg name: &CStr, 54d969d504SAndreas Hindborg block_size: u32, 55d969d504SAndreas Hindborg rotational: bool, 56d969d504SAndreas Hindborg capacity_mib: u64, 57*34585dc6SAndreas Hindborg irq_mode: IRQMode, 58d969d504SAndreas Hindborg ) -> Result<GenDisk<Self>> { 59d969d504SAndreas Hindborg let tagset = Arc::pin_init(TagSet::new(1, 256, 1), GFP_KERNEL)?; 60d969d504SAndreas Hindborg 61*34585dc6SAndreas Hindborg let queue_data = Box::new(QueueData { irq_mode }, GFP_KERNEL)?; 62*34585dc6SAndreas Hindborg 63d969d504SAndreas Hindborg gen_disk::GenDiskBuilder::new() 64d969d504SAndreas Hindborg .capacity_sectors(capacity_mib << (20 - block::SECTOR_SHIFT)) 65d969d504SAndreas Hindborg .logical_block_size(block_size)? 66d969d504SAndreas Hindborg .physical_block_size(block_size)? 67d969d504SAndreas Hindborg .rotational(rotational) 68*34585dc6SAndreas Hindborg .build(fmt!("{}", name.to_str()?), tagset, queue_data) 69d969d504SAndreas Hindborg } 70d969d504SAndreas Hindborg } 71d969d504SAndreas Hindborg 72*34585dc6SAndreas Hindborg struct QueueData { 73*34585dc6SAndreas Hindborg irq_mode: IRQMode, 74*34585dc6SAndreas Hindborg } 75*34585dc6SAndreas Hindborg 76edd86506SAndreas Hindborg #[vtable] 77edd86506SAndreas Hindborg impl Operations for NullBlkDevice { 78*34585dc6SAndreas Hindborg type QueueData = KBox<QueueData>; 7990d952faSAndreas Hindborg 80edd86506SAndreas Hindborg #[inline(always)] 81*34585dc6SAndreas Hindborg fn queue_rq(queue_data: &QueueData, rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result { 82*34585dc6SAndreas Hindborg match queue_data.irq_mode { 83*34585dc6SAndreas Hindborg IRQMode::None => mq::Request::end_ok(rq) 84edd86506SAndreas Hindborg .map_err(|_e| kernel::error::code::EIO) 85edd86506SAndreas Hindborg // We take no refcounts on the request, so we expect to be able to 86edd86506SAndreas Hindborg // end the request. The request reference must be unique at this 87edd86506SAndreas Hindborg // point, and so `end_ok` cannot fail. 88*34585dc6SAndreas Hindborg .expect("Fatal error - expected to be able to end request"), 89*34585dc6SAndreas Hindborg IRQMode::Soft => mq::Request::complete(rq), 90*34585dc6SAndreas Hindborg } 91edd86506SAndreas Hindborg Ok(()) 92edd86506SAndreas Hindborg } 93edd86506SAndreas Hindborg 94*34585dc6SAndreas Hindborg fn commit_rqs(_queue_data: &QueueData) {} 954ec05284SAndreas Hindborg 964ec05284SAndreas Hindborg fn complete(rq: ARef<mq::Request<Self>>) { 974ec05284SAndreas Hindborg mq::Request::end_ok(rq) 984ec05284SAndreas Hindborg .map_err(|_e| kernel::error::code::EIO) 994ec05284SAndreas Hindborg // We take no refcounts on the request, so we expect to be able to 1004ec05284SAndreas Hindborg // end the request. The request reference must be unique at this 1014ec05284SAndreas Hindborg // point, and so `end_ok` cannot fail. 1024ec05284SAndreas Hindborg .expect("Fatal error - expected to be able to end request"); 1034ec05284SAndreas Hindborg } 104edd86506SAndreas Hindborg } 105