nd_region

接着我们来看nd_region这个数据结构。

构造nd_region的函数

老规矩,先看看构造这个数据结构的函数样子。

acpi_nfit_register_regions()
  list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
    rc = acpi_nfit_register_region(acpi_desc, nfit_spa);
      struct nd_region_desc *ndr_desc;
      nfit_spa->nd_region = nvdimm_pmem_region_create(nvdimm_bus, ndr_desc);
  }

这是一个非常简略的构建流程,有几点含义想要表达:

  • nd_region的创建由一个acpi_desc->spa触发,并最后挂在spa上

  • 构造的过程中由一个中间变量ndr_desc,由它构造了最后的nd_region

相关的数据结构

这次的牵扯到的数据结构比较多了。

acpi_nfit_desc

    acpi_nfit_desc
    +-----------------------------------------------+
    |dev                                            | = point to an acpi_device
    |    (struct device*)                           |
    +-----------------------------------------------+
    |acpi_header                                    |
    |    (struct acpi_table_header)                 |
    +-----------------------------------------------+
    |spas                                           |  a list of nfit_spa
    |    (struct list_head)                         |  added from acpi_table
    |    +------------------------------------------+  
    |    |nd_region                                 |  *  created from nfit_spa
    |    |    (struct nd_region*)                   |
    |    |ars_state                                 |
    |    |    (unsigned long)                       |
    |    |spa[0]                                    |  looks just have one spa
    |    |    (struct acpi_nfit_system_address)     |
    |    |    +-------------------------------------+
    |    |    |header                               |
    |    |    |    (struct acpi_nfit_header)        |
    |    |    |range_guid[16]                       |
    |    |    |    (u8)                             |
    |    |    |range_index                          |
    |    |    |flags                                |
    |    |    |address                              |  spa address
    |    |    |length                               |
    |    |    |    (u16)                            |
    |    |    |                                     |
    |    +----+-------------------------------------+
    +-----------------------------------------------+

首先来看一下acpi_nfit_desc。其中有一个叫spas的链表。这个的数据在前期从acpi中读取并解析后保存在此。而其中的信息就是构造nd_region的基础。

nd_region_desc

这个结构就是用来构造nd_region的描述结构。在nvdimm驱动中已经是第二次看到这种描述结构了,看来驱动的作者挺喜欢这种方式。

其中在mapping字段可以看出当前nd_region和nvdimm之间的一个关联。

nd_region

最后就是nd_region这个结构本身了。其中大部分的数据是从刚才的 nd_region_desc 中拷贝过来的。

不过有意思的是,这个nd_region_desc之后就消失了,没有人会记得曾经还有个这么重要的角色。

补充一点,nd_regioin一共有三种类型:

  • nd_pmem

  • nd_volatile

  • nd_blk

这个类型的区分由dev->type的值来区分,对应上面三种类型各自的type值为:

  • nd_pmem_device_type

  • nd_volatile_device_type

  • nd_blk_device_type

到这里基本算可以结束了,但是我还想再往回推一层。那就是这个type的值是谁来决定的。

在本节的开头我们也看到了,每个nd_region是在acpi_nfit_desc->spa的基础上创建的。而在代码中也正好印证了这一点。nd_region->type也是基于spa的类型决定的。

这个函数将spa->range_guid和一个表比较,从而得出当前spa的类型,也就是nd_region的类型了。

nd_region_driver

当一个nd_region构造好了之后,其对应的驱动就该登场干活了。这次就是nd_region_driver,而且还干了不少活。

其做了一些初始化的工作后又做了几件重要的事:

  • 创建namespace

  • 创建btt/pfn/dax设备

接下来我们就分步骤看看这几个重要的设备的创建过程。

Last updated

Was this helpful?