Linux Scsi子系统框架介绍( 四 )


文章插图
 

Linux Scsi子系统框架介绍

文章插图
 

Linux Scsi子系统框架介绍

文章插图
 
只有符合指定类型的设备 , 才会触发对应的驱动程序 。
三、主体代码描述linux驱动子系统 , 一般包含下面几个内容:
  • 子系统初始化:驱动bus的建立 , 子设备驱动的挂载 。
  • 外设扫描:对于scsi而言就是把device侧的所有lun扫描出来 。
  • 通路建立:建立子设备驱动和device之间的连接 , 对于scsi而言就是公版外设驱动和lundevice之间的通路 。Scsi子系统是借助block通用块设备层完成这部分工作 。
  • 休眠唤醒:对于scsi而言 , 休眠过程是lun->target->host , 唤醒过程是反过来 。这个决定了host是爷爷辈设备 , targe是父设备 , lun是子设备 , 所有的公版驱动都是子设备驱动 。
1.子系统初始化代码位置:kernel/drivers/scsi/scsi.c
Linux Scsi子系统框架介绍

文章插图
 
(1) Scsi_init_queue:这个函数主要是创建scsi cmd和sense cache用到的slab内存 , 这样后续scsi cmd和sense都可以在slab中申请内存 , 加快内存申请速度 。
(2)Scsi_init_procfs:这个是创建一个/proc/scsi/scsi的文件节点
这个节点会显示当前系统注册了哪些scsi设备 , 包括这些设备的channel编号,id编号 lun编号等信息 。
这些信息都是实时变化的;如果有写入动作 , 也会触发子系统的scan动作 。
Linux Scsi子系统框架介绍

文章插图
 
(3) Scsi_init_devinfo这个函数创建了/proc/scsi/device_info节点 。
这个节点有点像kernel 里面常用的quirk等fix机制 , 内容如下
Linux Scsi子系统框架介绍

文章插图
 

Linux Scsi子系统框架介绍

文章插图
 
结构体的前面三类分别是vendor,model和revision , 其实就是scsi inquiry命令返回的数据 , 最后一个是个整形flag值 , 这个flag值影响着设备的初始话过程和操作过程 。例如BLIST_NOLUN会让scsi扫描外设时 , 只扫描lun0 。
(4) Scsi_init_sysctl这个函数创建了一个/proc/sys/dev/scsi/logging_level节点 , 这个节点控制着scsi子系统debug打印的log等级 , 值越小 , 打印越少 。
(5) Scsi_init_hosts和scsi_sysfs_register这两个函数创建了scsi子系统最关键的bus和class(“scsi”, “scsi_host”和“scsi_device”):
2.子设备驱动加载这类驱动加载一般比较简单 , 而且单独以module形式 , 耦合性很小 。它们一般在module初始化时注册到”scsi” bus总线上 , 然后一直等待有对应的子设备sdev_devgen挂到”scsi” bus上来 。例如:
Linux Scsi子系统框架介绍

文章插图
 
3.外设扫描Scsi扫描过程定义: 是识别每个host , 每个targe和每个lun , 给其创建对应的device结构 , 并将device挂载到相应的bus或class上 。
设备扫描的方式很多:
  • 以host为单位进行scan 。它会把host对应的device下面所有的target和lun全扫描出来 。
  • 以target为单位触发scsi进行scan 。它会把target下面所有的lun全扫出来
  • 以lun为单位触发scsi进行scan 。它会扫描特定lun 。
  • 通过/proc/scsi/scsi触发特定的target或lun的scan 。
  • 通过host对应user空间设备的属性”scan”节点触发特定的target或lun的scan 。
(1) Host扫描由于host控制器各个芯片平台不一样 , 它的扫描过程是host device的父设备所在驱动完成的 , 它的父设备驱动可以是platform总线 , 也可以是pcie设备对应的pci_driver , 也可以是ufs子系统(ufshcd.c)等等 。
例如我电脑上 , host设备是名为”ahci”的pci_driver扫描创建的控制器 , 一共有6个控制器 , 其中只有host4这个控制器上接了一块硬盘 。
Linux Scsi子系统框架介绍

文章插图
 
无论哪种当上一级驱动找到host后 , 会通过下面的
scsi_host_alloc:创建shost_gendev和shost_dev 。


推荐阅读