weixin_45400120 2021-04-08 11:23 采纳率: 0%
浏览 15

模块init的时候会注册两次, 导致模块加载不进去

static int pmem_major

static struct pmem_device *shebei;

static int __init pmem_init(void)
{
        int error;

       pmem_major = register_blkdev(0, "pmem");

        if (pmem_major < 0)
 

                return pmem_major;

        error = nd_driver_register(&nd_pmem_driver);
        if (error)

                nregister_blkdev(pmem_major, "pmem");
                return error;
        }

        return 0;
}
module_init(pmem_init);

 

struct pmem_device {
        struct request_queue    *pmem_queue;
        struct gendisk          *pmem_disk;
        struct nd_namespace_common *ndns;

        /* One contiguous memory region per device */
        phys_addr_t             phys_addr;
        /* when non-zero this device is hosting a 'pfn' instance */
        phys_addr_t             data_offset;
        void __pmem             *virt_addr;
        size_t                  size;
};

static int nd_pmem_probe(struct device *dev)
{
 extern int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns);

        struct nd_region *nd_region = to_nd_region(dev->parent);
        struct nd_namespace_common *ndns;
        struct nd_namespace_io *nsio;
        struct pmem_device  *pmem;

        ndns = nvdimm_namespace_common_probe(dev);
        if (IS_ERR(ndns))
                return PTR_ERR(ndns);

        nsio = to_nd_namespace_io(&ndns->dev);
        pmem = pmem_alloc(dev, &nsio->res, nd_region->id);
        if (IS_ERR(pmem))
                return PTR_ERR(pmem);

        pmem->ndns = ndns;
        dev_set_drvdata(dev, pmem);
        ndns->rw_bytes = pmem_rw_bytes;

        if (is_nd_btt(dev))
                return nvdimm_namespace_attach_btt(ndns);

        if (is_nd_pfn(dev))
                return nvdimm_namespace_attach_pfn(ndns);

        if (nd_btt_probe(ndns, pmem) == 0) {
                /* we'll come back as btt-pmem */
                return -ENXIO;
        }

        if (nd_pfn_probe(ndns, pmem) == 0) {
                /* we'll come back as pfn-pmem */
                return -ENXIO;
        }

        return pmem_attach_disk(dev, ndns, pmem);
}

 

static struct pmem_device *pmem_alloc(struct device *dev,
                struct resource *res, int id)
{
        struct pmem_device *pmem;

        pmem = devm_kzalloc(dev, sizeof(*pmem), GFP_KERNEL);
        if (!pmem)
                return ERR_PTR(-ENOMEM);

        pmem->phys_addr = res->start;
        pmem->size = resource_size(res);
        if (!arch_has_wmb_pmem())
                dev_warn(dev, "unable to guarantee persistence of writes\n");

        if (!devm_request_mem_region(dev, pmem->phys_addr, pmem->size,
                        dev_name(dev))) {
                dev_warn(dev, "could not reserve region [0x%pa:0x%zx]\n",
                                &pmem->phys_addr, pmem->size);
                return ERR_PTR(-EBUSY);
        }

        if (pmem_should_map_pages(dev))
                pmem->virt_addr = (void __pmem *) devm_memremap_pages(dev, res);
        else
                pmem->virt_addr = (void __pmem *) devm_memremap(dev,
                                pmem->phys_addr, pmem->size,
                                ARCH_MEMREMAP_PMEM);

        if (IS_ERR(pmem->virt_addr))
                return (void __force *) pmem->virt_addr;

        return pmem;
}

static int pmem_attach_disk(struct device *dev,
                struct nd_namespace_common *ndns, struct pmem_device *pmem)
{
        int nid = dev_to_node(dev);
        struct gendisk *disk;

        pmem->pmem_queue = blk_alloc_queue_node(GFP_KERNEL, nid);
        if (!pmem->pmem_queue)
                return -ENOMEM;

        blk_queue_make_request(pmem->pmem_queue, pmem_make_request);
        blk_queue_physical_block_size(pmem->pmem_queue, PAGE_SIZE);
        blk_queue_max_hw_sectors(pmem->pmem_queue, UINT_MAX);
        blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY);
        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, pmem->pmem_queue);

        disk = alloc_disk_node(0, nid);
        if (!disk) {
                blk_cleanup_queue(pmem->pmem_queue);
                return -ENOMEM;
        }

        disk->major             = pmem_major;
        printk("diskmajor=%d\n",pmem_major);
        disk->first_minor       = 0;
        disk->fops              = &pmem_fops;
        disk->private_data      = pmem;
        disk->queue             = pmem->pmem_queue;
        disk->flags             = GENHD_FL_EXT_DEVT;
        nvdimm_namespace_disk_name(ndns, disk->disk_name);
        disk->driverfs_dev = dev;
        set_capacity(disk, (pmem->size - pmem->data_offset) / 512);
        pmem->pmem_disk = disk;
        shebei = pmem;   //  我在这设置了一个自己的指针指向了这个设备!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        printk("aaapmemchengg\n");

        add_disk(disk);
        revalidate_disk(disk);

        return 0;
}

 

我希望用到一个设备,他在初始化的时候调用alloc为设备分配内存.我自己在驱动之中设置了一个指针   指向了那块被初始化的地方 打算利用他 

(最后  模块没有加载进去 但是/proc/device能看到第一次载入的设备号)

  • 写回答

1条回答 默认 最新

  • 码农阿豪@新空间代码工作室 Java领域优质创作者 2024-07-18 18:28
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    To answer this question, first I will break down the code snippet provided into logical parts and explain their functionality.
    1. pmem_major and shebei are declared as static integers and a pointer to a struct pmem_device, respectively.
    2. The pmem_init function is an initialization function that registers a block device with the name "pmem".
    3. The pmem_device struct defines the characteristics of a persistent memory device.
    4. The nd_pmem_probe function is a probe function that handles the probing of persistent memory devices.
    5. The pmem_alloc function allocates memory for a persistent memory device.
    6. The pmem_attach_disk function attaches a disk to a persistent memory device. Now, let's provide an example:
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/device.h>
    #include <linux/nd.h>
    #include <linux/resource.h>
    #include <linux/ioport.h>
    static int pmem_major;
    static struct pmem_device *shebei;
    static int __init pmem_init(void)
    {
        int error;
        pmem_major = register_blkdev(0, "pmem");
        if (pmem_major < 0)
            return pmem_major;
        error = nd_driver_register(&nd_pmem_driver);
        if (error)
        {
            unregister_blkdev(pmem_major, "pmem");
            return error;
        }
        return 0;
    }
    module_init(pmem_init);
    struct pmem_device {
        struct request_queue *pmem_queue;
        struct gendisk *pmem_disk;
        struct nd_namespace_common *ndns;
        phys_addr_t phys_addr;
        phys_addr_t data_offset;
        void __pmem *virt_addr;
        size_t size;
    };
    static int nd_pmem_probe(struct device *dev)
    {
        struct nd_region *nd_region = to_nd_region(dev->parent);
        struct nd_namespace_common *ndns;
        struct nd_namespace_io *nsio;
        struct pmem_device *pmem;
        ndns = nvdimm_namespace_common_probe(dev);
        if (IS_ERR(ndns))
            return PTR_ERR(ndns);
        nsio = to_nd_namespace_io(&ndns->dev);
        pmem = pmem_alloc(dev, &nsio->res, nd_region->id);
        if (IS_ERR(pmem))
            return PTR_ERR(pmem);
        pmem->ndns = ndns;
        dev_set_drvdata(dev, pmem);
        ndns->rw_bytes = pmem_rw_bytes;
        // Handle different cases based on the device type
        if (is_nd_btt(dev))
            return nvdimm_namespace_attach_btt(ndns);
        if (is_nd_pfn(dev))
            return nvdimm_namespace_attach_pfn(ndns);
        
        return pmem_attach_disk(dev, ndns, pmem);
    }
    static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res, int id)
    {
        struct pmem_device *pmem;
        pmem = devm_kzalloc(dev, sizeof(*pmem), GFP_KERNEL);
        
        if (!pmem)
            return ERR_PTR(-ENOMEM);
        pmem->phys_addr = res->start;
        pmem->size = resource_size(res);
        // Additional checks and memory allocation
        // ...
        return pmem;
    }
    static int pmem_attach_disk(struct device *dev, struct nd_namespace_common *ndns, struct pmem_device *pmem)
    {
        int nid = dev_to_node(dev);
        struct gendisk *disk;
        
        pmem->pmem_queue = blk_alloc_queue_node(GFP_KERNEL, nid);
        
        if (!pmem->pmem_queue)
            return -ENOMEM;
        
        // Configure block device queue
        // ...
        return 0;
    }
    

    This example simplifies the code snippet provided and showcases how these functions and structs might be used in a kernel module. Each function has a specific role; pmem_init initializes the block device, nd_pmem_probe probes the device, pmem_alloc allocates memory for the device, and pmem_attach_disk attaches a disk to the device.

    评论

报告相同问题?

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵