nvdimm

创建了nvdimm_bus,读取了nfit中的信息后,接下来驱动就根据这些信息创建nvdimm这个数据结构了。

这个数据结构就对应着一个物理的dimm,这可能也是为什么使用memmap=内核参数时没有这个设备的原因。

构造nvdimm的函数

这个过程由acpi_nfit_register_dimms()函数完成,大致的流程如下:

list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
    __nvdimm_create();
}

从这个片段能看出nvdimm结构体是从acpi_desc->dimms的信息构建的。

相应的数据结构

看了函数调用,现在来看看对应的数据结构的样子。虽然看了有时候也还是不懂。

    acpi_nfit_desc
    +-----------------------------------------------+
    |dimms                                          |  a list of nfit_mem
    |    (struct list_head)                         |  parsed from above spa & memdevs
    |    +------------------------------------------+
    |    |nvdimm                                    |  *
    |    |     (struct nvdimm*)                     |
    |    |     +------------------------------------+
    |    |     |dev                                 |
    |    |     |   (struct device)                  |
    |    |     |   +--------------------------------+
    |    |     |   |name                            |  = "nmem%d"
    |    |     |   |groups                          |  = acpi_nfit_dimm_attribute_groups
    |    |     |   |                                |
    |    |     |   |driver_data                     |  = struct nvdimm_drvdata
    |    |     |   |   (void*)                      |
    |    |     |   |  +-----------------------------+
    |    |     |   |  |dev                          |
    |    |     |   |  |   (struct device*)          |
    |    |     |   |  |ns_current, ns_next          |
    |    |     |   |  |nslabel_size                 |  = 128
    |    |     |   |  |   (int)                     |
    |    |     |   |  |nsarea                       |
    |    |     |   |  |     (nd_cmd_get_config_size)|
    |    |     |   |  |data                         |  config data
    |    |     |   |  |   (void*)                   |  namespace index + namespace label
    |    |     |   |  |dpa                          |  created from namespace label
    |    |     |   |  |   (struct resource)         |  from nvdimm_drvdata->data
    |    |     |   |  +-----------------------------+
    |    |     |   |                                |
    |    |     |   +--------------------------------+
    |    |     |provider_data                       |  = nfit_mem
    |    |     |   (void*)                          |
    |    |     |flush_wpq                           |
    |    |     |   (struct resource*)               |
    |    |     |dwork                               |
    |    |     |   (struct delayed_work)            |
    |    |     |sec.ops                             |
    |    |     |                                    |
    |    |     |                                    |
    |    +-----+------------------------------------+
    |    |memdev_dcr                                |
    |    |memdev_pmem                               |
    |    |memdev_bdw                                |
    |    |     (struct acpi_nfit_memory_map)        |
    |    |                                          |
    |    +------------------------------------------+
    |                                               |
    +-----------------------------------------------+

在这个数据结构的部分截取中可以看到,acpi_nfit_desc中包含了一个类型为nfit_mem的链表。而函数acpi_nfit_register_dimms就是根据这个链表来构造硬件相对无关的nvdimm数据。

nvdimm_driver

nvdimm对应的是一个物理的dimm,这个设备生成之后就需要去检查并初始化。这个工作由它的驱动nvdimm_driver来完成。

驱动做的关键工作就是根据硬件信息设置这个数据结构中的dev->driver_data。

这个结构是一个nvdimm_drvdata类型,其具体的成员也已经在图中显示。主要解释其中两个内容:

  • data: 驱动将硬件上的namespace index和namespace label_size读取到这段内存

  • dpa: 驱动根据上面的data信息,将dimm对应的dpa信息转换成res树

我猜这些信息会留着后续使用,那就等着看吧。

Last updated