PM8001驱动及相关模块分析——综述及初始化

来源:互联网 发布:易推客营销软件下载 编辑:程序博客网 时间:2024/05/29 12:11


前言

PM8001驱动是linux标准内核自带的HBA驱动,由于完全开源,所以对于学习linux存储系统底层很有帮助。笔者有幸在之前的工作中使用过这款HBA,所以结合实际使用和源码稍微记录一下。由于已经过去很久了,现在重新拿起来看,有些地方理解的会有疏忽,敬请谅解和多提宝贵意见。

对于PM8001这个设备,其与主机通过PCI总线连接,属于SCSI子系统中的底层模块。SCSI子系统按功能和逻辑结构可以划分成三层。系统结构如图所示。



本文的主线是根据PM8001驱动(较低层)来展开,其间会涉及到中间层相关部分的分析,但对于顶层涉及得不多。

  1. scsi子系统中间层和较低层简要分析

    1. scsi中间层功能简介

在进行对pm8001驱动分析之前,先简要根据我的理解分析一下scsi子系统中的中间层和较低层。

中间层顾名思义是介于scsi子系统顶层和较低层之间的层次。中间层是scsi子系统分层模型核心意义的体现——它能够解除顶层和较低层之间的耦合,并为顶层和较低层提供一系列服务。中间层能够解除顶层与较低层的耦合关键在于中间层提供了LLD的抽象接口scsi_host和能够复刻scsi_host对象的scsi_host_template。当较低层将scsi_host注册到中间层后,中间层即可以调用lld相关函数。同理,顶层的驱动也可以通过中间层间接地使用lld的函数。所以在lldd(pm8001驱动)初始化时,先实例化一个scsi_host_template对象,将本身的一些函数实现挂载到这个对象中,然后在后续的pci设备的probe函数中将这个对象以及对应的scsi_host注册到中间层。

中间层出了解耦合功能以外,也起到了转换器的作用,即中间层会把从顶层传入的请求操作转换成scsi命令。在我们的体系中,中间层将请求转换成scsi命令后发向llddlldd会将命令通过IBQ发往pm8001pm8001scsi命令转换成sas命令发向指定地址的phy

另外中间层也提供一系列很重要的函数,比如scsi总线扫描算法,错误处理等。


  1. libsas的关系

根据我的理解,libsaspm8001(可能还会有其他辅助函数库)共同构成了给予pm8001板卡的scsi子系统中较低层的实现。Libsaspm8001分别承担不同的责任,pm8001直接与硬件设备进行交互,更多地关注较为底层的基础构建部分;libsas部分则包含了大量的逻辑性代码,负责对数据(上行/下行)进行封装处理或对事件进行响应。

Pm8001提供了一系列与物理设备相关的函数(sas_domain_function_template结构体中,以lldd开头),在初始化时会被注册到libsas中,libsas中的部分逻辑最终通过调用这些函数来实现实际底层的操作。

pm8001驱动注册到scsi子系统时,注册过程在pm8001中完成,但注册的函数在libsas中实现。Pm8001中的中断响应函数,在进行底层初步处理(与pm8001硬件特性有关,具体参见pm8001编程手册)后,会把事件递交给libsas层对应函数进行进一步处理。

  1. pm8001初始化过程分析

pm8001的初始化入口在pm8001_init.c中。

  1. 初始化scsi_transport_template结构。scsi_transport_template结构体内包含了一系列scsi命令传输所需要用到的参数以及相关函数,这些函数由libsas层提供。在初始化scsi_transport_template的过程中,会有一个sas_internal中间结构,这个结构中包含有一系列libsas层在运行中所需要用到的函数模板、参数等信息,其内部有一个字段对应scsi_transport_template结构,可以通过两者之一获取对方从而调用其包含的函数。

  2. 初始化pm8001PCI相关部分。

在初始化PCI相关部分的时候,我们可以注意到其中的probe函数会在主机查询到了PCI设备(这里指PM8001)时进行调用,其主要功能在于对pm8001设备进行真正意义上的初始化。

  1. PCI相关配置操作。

  2. 创建一个scsi_host实例。前面有提到过scsi_hostlldd被中间层调用的接口,它是pm8001驱动链入到整个scsi子系统的关键结构体之一。在这里通过调用scsi_host_alloc函数对其进行初始化,这个函数中会对其进行参数配置,但主要的实例化过程是通过将scsi_host中的一些字段用scsi_host_template结构中的字段赋值。此外,在初始化的过程中也会在虚拟文件系统中做相应的注册。

  3. 初始化pm8001_chip_infopm8001_chip_info结构代表着scsi_host_chip,在这个结构体中有一个pm8001_dispatch结构,其中包含了一系列底层逻辑过程。这些底层逻辑过程大多数都跟设备行为有关,详细信息可以参考编程手册。这些底层逻辑过程实际上是根据约定对事件或数据进行分发,而真正意义上的对硬件的操作是集中在pm8001_hwi.c中一系列以mpi为开头的函数;对逻辑的处理最终通过转发给libsas层相关函数进行处理。

  4. 初始化sas_ha_structsas_ha_struct结构体是lldlibsas层的抽象,libsas层可以通过该结构体完成逻辑。

  5. 初始化pm8001_hba_info结构。pm8001_hba_info结构体是对pm8001的抽象,这个结构体在后续逻辑中会被经常使用。其中包含了一系列已经绑定的处理函数和相关参数,是程序运行的核心。

  6. 软复位
    软复位的一系列操作可以参见pm8001编程手册,值得一提的是这里有普通和had两种模式,区别在于载入spc 8x6G固件镜像的方式不同。

  7. 初始化chip

Chip的初始化主要是针对一些硬件设备级的配置信息,这些主要是通过配置MPI配置表来完成,MPI配置表具体信息参见编程手册第五章。在PM8001的驱动中并不会(也不需要)对所有参数进行配置。

  1. 中断注册

  2. 初始化sas地址

  3. 注册hba设备。这个操作是由libsas层的函数提供的处理方法完成处理,最终会启动一条工作处理线程。

  4. 执行扫描scsi总线。这个操作由scsi子系统中间层提供,用于扫描scsi总线,获取节点。在扫描到节点会执行添加lun操作。执行scsi扫描操作的前后都可以注册start/finish函数,这些函数是在pm8001中实现,包含了一些底层的初始化过程。

0 0
原创粉丝点击