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


scsi_add_host: 把shost_gendev和shost_dev挂靠到各自的bus或class上 。
(2) Target和lun扫描

Linux Scsi子系统框架介绍

文章插图
 
从前面的硬件建模上来看 , 它的扫描过程是
  • 先从0开始for循环扫描channel
  • 在每个channel循环下面再for循环扫描每个id
  • 在每个id下面再for循环扫描所有的lun伪码如下:

Linux Scsi子系统框架介绍

文章插图
 
以scsi_scan_host为例 , 这个函数是以host为单位进行全扫描
Linux Scsi子系统框架介绍

文章插图
 
(3) 各种scan入口
  • 以host为单位进行scan:scsi_scan_host
  • 以target为单位触发scsi进行scan:scsi_scan_target
  • 以lun为单位触发scsi进行scan:scsi_add_device或者__scsi_add_device
  • 通过/proc/scsi/scsi:scsi_scan_host_selected
  • 通过host对应user空间设备的属性“scan”节点:scsi_scan_host_selected
4.通路建立:借助block层Scsi注册block层有两个方式 , 一种是single q , 另一种是multi q方式 , 这里介绍multi q的方式 。
注册multi q , 需要做两件事情
  • 通过blk_mq_alloc_tag_set注册一个blk_mq_tag_set 。注册时我们要提供一堆钩子函数给通用块设备层 , 处理block发下来的request请求 。
  • 通过blk_mq_init_queue并以blk_mq_tag_set为参数为每个能独立处理block请求的实体申请一个request_queue 。这样所有的request_queue都和tag_set关联起来了 。
通过上述操作后 , 所有发送到request_queue中的request都会汇集到tag_set中做处理 。
前面讲了host(k)和device(k)中间的双箭头是scsi命令的传输通道 , lun是接收和处理scsi命令的实体 。因此和block层关联的
  • 第一步是在创建shost_devgen或者shost_dev的地方做的 。
 
Linux Scsi子系统框架介绍

文章插图
 
  • 第二步是在创建sdev_dev或者sdev_devgen的地方做的 。

Linux Scsi子系统框架介绍

文章插图
 
代码截图:
第1步
Linux Scsi子系统框架介绍

文章插图
 

Linux Scsi子系统框架介绍

文章插图
 

Linux Scsi子系统框架介绍

文章插图
 
第2步
Linux Scsi子系统框架介绍

文章插图
 
至此外界任何发送给lun的请求都会进入到lun相关的request_queue , 例如通过ioctl对sda或者sg设备的命令request都会进入到其对应lun的request_queue 。最终都会走到tag_set的queue_rq钩子函数 , 也就是走到了scsi_queue_rq->scsi_dispatch_cmd->host->hostt->queuecommand函数 , 其中queuecommand是底层驱动注册上来的钩子函数 , scsi子系统把request请求发送到这一步之后 , 剩下的工作就交给底层类似于ufs , sata驱动去处理了 。例如 , ufs会根据请求的类型把上层传下来的信息封装成upiu发给硬件控制器 , 从而完成一次传输 。
5.休眠唤醒休眠唤醒是驱动的一部分 , 包括PM(suspendresume) , runtime PM , 也有shutdown , remove等 。以休眠为例:在”scsi” bus上那些公版driver实现了子设备的休眠唤醒操作 。这个级别的驱动操作的都是lun设备 , 因此这个级别的驱动是基于scsi命令对设备进行操作 。那些更底层的操作例如断开link , 给外设断电等是更底层的父设备们去完成的 。例如
  • 硬盘驱动sd.c在休眠的时候 , 给lun发送了scsiSYNCHRONIZE_CACHE命令 , 要求lun把缓存数据回写到硬盘防止断电丢失 , 并发送了start_stop命令要求lun进入低功耗状态 。

Linux Scsi子系统框架介绍

文章插图
 
  • 光盘驱动sr.c在连休眠唤醒没有实现 , 只有一个runtime pm操作啥也没做 , 可能它的功耗是由光驱自动控制的 , 不需要软件参与 。
 
Linux Scsi子系统框架介绍

文章插图
 
Linux设备驱动模型会保证子设备suspend之后 , 才会是父设备的suspend , 向底层一级一级父辈驱动的suspend调用 。


推荐阅读