BLOCK层代码分析(6)IO下发之SGL聚散列表

        原本计划本节介绍request的分配,发现会涉及到数据组织从bio到sgl的映射,因此本节介绍数据的SGL组织方式。

 

        在BLOCK层数据的组织形式为bio和request,通过这两个结构体就可以找到数据的位置。但若传输到SCSI层,硬盘位置用scsi command表示,内存中位置用scatterlist表示。本小节讲述scatterlist是如何将数据组织起来的。

1. scatterlist结构体

        结构体scatterlis包含从CPU视角和设备视角看到的数据的地址和长度(包括页内偏移)。但其中page_link有两个特殊作用:(1)当第0 bit为1时即设置SG_CHAIN,表明当前sgl是链接sgl,只起链接到下一个sgl的作用,这个sgl不会指向数据;(2)当第1bit为1时即设置SG_END,表明当前sgl是最后一个sgl,这个sgl仍指向数据。当其他情况时指向数据对应的第一个页信息。

        成员offset表示数据在页中的偏移。成员length表示数据的长度。

        成员dma_address表示数据的DMA地址即设备看到的地址,成员dma_length表示数据的DMA长度。

2. SGL类型

        SGL分为non-chained SGL和chained SGL。

        Non-chained SGL表示多个sgl是连续的,内核这里对最大的non-chained SGL数目做限制,最大不超过SG_MAX_SINGLE_ALLOC,当申请的SGL个数超过此限制时会自动生成chained SGL。

        Chained SGL存在多个的SGL链,每个SGL链中的SGL是连续的,其中每个SGL链(除了最后一个SGL链)最后一个SGL起链接作用。每个SGL链最大的SGL数目为SG_CHUNK_SIZE(128)。

3. SGL API介绍

        函数sg_alloc_table()用来分配non-chained SGL(当申请的数目nents超过限制时,也会生成chained SGL)。

int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)

        函数sg_alloc_table_chained()来分配chained SGL。其中nents为需要分配的SGL数目,first_chunk为sg_table中已经存在的SGL链,SGL链数目为first_chunk_nents。后面申请的SGL链与first_chunk相链。

​
int sg_alloc_table_chained(struct sg_table *table, int nents, struct scatterlist *first_chunk, unsigned nents_first_chunk)

        两者最终会调用__sg_alloc_table()。这里处理四种情况:

(1)first_chunk = NULL, nents <= max_ents时

        这种情况为sg_table,并没有提前分配SGL链,且需要分配SGL数目小于最大一次性能够分配的数目,此时通过alloc_fn()直接分配即可,生成non-chained SGL链。

(2)first_chunk = NULL, nents > max_ents时

        这种情况为sg_table,并没有提前分配SGL链,且需要分配SGL数目大于最大一次性能够分配的数目,此时通过alloc_fn()会分配一个包含max_ents数目的SGL的SGL链,剩下的部分分配另一个SGL链,并将它们链起来,生成chained SGL链。

(3)first_chunk != NULL, nents <= max_ents时

        这种情况为sg_table,提前分配SGL链, 且提前分配的SGL链上SGL数目满足需要的SGL链,此时会直接返回当前的sg_table。

(4)first_chunk != NULL, nents > max_ents时

         这种情况为sg_table,提前分配SGL链, 但提前分配的SGL链上SGL数目不能够满足nents数目,此时需要通过alloc_fn()分配剩余的数目的SGL组成SGL链,并与提供分配的SGL链连接起来,生成chained SGL链。

4. SCSI命令的SGL

        在SCSI层在分配request时默认内置了2个SGL(实际真正使用的仅1个,另一个做链接SGL使用),在申请时使用sg_alloc_table_chained(&cmd->sdb.table, nr_segs, cmd->sdb.table.sgl, SCSI_INLINE_SG_CNT)申请链式SGL。

        下图为申请150个SGL的情况,其中内置2个SGL为第一个SGL链,这个是随request提前分配的(静态分配),后面两个SGL链是从sgpool中申请分配的(动态分配)。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PCI8系列 PCI9系列 PCI9054 linux驱动程序 PLX SDK Samples ================================================================ ABOUT This document provides a brief description of the samples included in the PLX SDK. Please refer to the source code in each sample & the PLX SDK User's Manual for additional details. The PLX samples are intended to demonstrate use of the PLX API. The samples are not intended for debug or real world applications, although they can be extended to complex applications. They should be treated as a reference for writing custom software that utilizes the PLX API. Not all samples work with all PLX devices. The PLX API supports numerous PLX chip families in PCI/PCIe, including 6000-series PCI-to-PCI bridges, 9000-series PCI-to-Local bus bridges, & 8000-series PCI/PCIe bridges & switches. Some samples are provided only for specific chip families. SAMPLES - ApiTest Simple application that calls various PLX APIs for a selected device & verifies return codes & parameters. The API calls made depend upon the type of device selected. - DSlave Demonstrates how to read/write from a PLX 9000 PCI BAR space using the PLX API/driver to perform the data transer. This operation is often referred to as "Direct Slave". - DSlave_BypassApi Similar to the 'DSlave' sample, except this sample uses the PLX API only to map a PCI BAR space directly to the application's virtual space. The application can then directly access the space via simple memory dereferencing, bypassing the PLX API/driver & resulting in greater performance, especially for small transfers. The application is responsible for initializing the BAR space, such as setup of translation/remap registers. - LocalToPciInt [9000-series & 8311] Demonstrates how to wait for a generic Local-to-PCI interrupt using the PLX Notification API. - NT_DmaTest [8000-series switches with DMA & NT support] Demonstrates using the DMA engine in a PLX 8000 switch to transfer data through a PLX

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值