SCSI系列三:linux SCSI 子系统六十一-hisi_sas(3)

文章详细描述了HISISAS控制器中用于存储和管理SCSI命令和数据传输的内存结构,包括SGE页面、带有DIF的SGE页面、命令表(如SSP、SMP和STP)、状态缓冲区及数据完整性支持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hisi_sas_sge_page & hisi_sas_sge_dif_page


#define HISI_SAS_SGE_PAGE_CNT (124)
struct hisi_sas_sge_page {
	struct hisi_sas_sge sge[HISI_SAS_SGE_PAGE_CNT];
}  __aligned(16);

#define HISI_SAS_SGE_DIF_PAGE_CNT   HISI_SAS_SGE_PAGE_CNT
struct hisi_sas_sge_dif_page {
	struct hisi_sas_sge sge[HISI_SAS_SGE_DIF_PAGE_CNT];
}  __aligned(16);

这段代码定义了两个数据结构用于管理存储在 HisiSAS 控制器中的 SGE(Scatter-Gather Element)页面。SGE 页面用于存储散列-聚合元素,这些元素指向存储数据的位置,是存储传输的关键部分。

hisi_sas_sge_page 结构体

  • sge:一个包含 HISI_SAS_SGE_PAGE_CNThisi_sas_sge 结构体的数组,用于存储 SGE 元素。这些元素表示在数据传输过程中散射-聚合的不同数据块。

hisi_sas_sge_dif_page 结构体

  • sge:与上述类似,这也是一个包含 HISI_SAS_SGE_DIF_PAGE_CNThisi_sas_sge 结构体的数组,用于存储带有 DIF(Data Integrity Field)的 SGE 元素。DIF 可用于验证和保护存储数据的完整性。

这两个结构体的数组成员 sge 用于存储多个 SGE 元素,每个元素描述了一个数据块的位置和属性,以支持存储传输。整个结构体定义中的 __aligned(16) 指定了内存对齐方式,确保这些页面在内存中按照一定的对齐方式存储。

hisi_sas_command_table_ssp


struct hisi_sas_command_table_ssp {
	struct ssp_frame_hdr hdr;
	union {
		struct {
			struct ssp_command_iu task;
			u32 prot[7];
		};
		struct ssp_tmf_iu ssp_task;
		struct xfer_rdy_iu xfer_rdy;
		struct ssp_response_iu ssp_res;
	} u;
};

这段代码定义了 hisi_sas_command_table_ssp 结构体,该结构体用于描述一个用于 SSP(SCSI Serial Protocol)的命令表。SSP 是一种在 SAS(Serial Attached SCSI)协议中使用的命令协议,用于传输 SCSI 命令和数据。

  • hdr:一个 ssp_frame_hdr 结构体,表示 SSP 帧的头部,包含了帧的控制信息。

  • u:一个联合体,包含了多种不同类型的 SSP 命令的数据结构。根据实际使用情况,其中的一个成员会被选中。

    • task:一个 ssp_command_iu 结构体,表示 SSP 命令的主体部分,包括 SCSI 命令和相关的传输参数。
    • prot:一个包含 7 个元素的整数数组,用于存储 SCSI 数据保护信息。
    • ssp_task:一个 ssp_tmf_iu 结构体,表示 SSP 任务管理帧。
    • xfer_rdy:一个 xfer_rdy_iu 结构体,表示 SSP 数据传输准备就绪帧。
    • ssp_res:一个 ssp_response_iu 结构体,表示 SSP 响应帧。

根据不同的 SSP 命令类型,联合体中的不同成员会被填充。这个结构体用于描述 SSP 命令在内存中的布局,以便在传输过程中正确解析和处理 SSP 命令。

hisi_sas_command_table


union hisi_sas_command_table {
	struct hisi_sas_command_table_ssp ssp;
	struct hisi_sas_command_table_smp smp;
	struct hisi_sas_command_table_stp stp;
}  __aligned(16);

这段代码定义了一个联合体 hisi_sas_command_table,用于在相同的内存区域内表示不同类型的命令表,包括 SSP、SMP 和 STP 命令表。

  • ssp:一个 hisi_sas_command_table_ssp 结构体,用于表示 SSP 命令表。
  • smp:一个 hisi_sas_command_table_smp 结构体,用于表示 SMP 命令表。
  • stp:一个 hisi_sas_command_table_stp 结构体,用于表示 STP 命令表。

这个联合体的目的是将不同类型的命令表放在同一块内存区域中,以便于内存的分配和管理。这样,在特定的场景下,可以根据实际需要选择相应的结构体成员来填充命令表,然后使用这个联合体进行操作。整个联合体的大小将按照 16 字节对齐。

在某些情况下,可能会根据具体的命令类型选择不同的成员来填充联合体,从而实现不同类型的命令在同一块内存区域内的表示。

hisi_sas_status_buffer

struct hisi_sas_status_buffer {
	struct hisi_sas_err_record err;
	u8	iu[1024];
}  __aligned(16);

这段代码定义了一个结构体 hisi_sas_status_buffer,用于在同一块内存区域内表示状态缓冲区。这个缓冲区用于存储命令的状态信息以及相关的错误记录。

  • err:一个 hisi_sas_err_record 结构体,用于存储错误记录。
  • iu:一个 1024 字节大小的缓冲区,用于存储命令相关的信息单元(Information Unit)。

这个结构体的目的是将命令的状态信息和错误记录存储在同一块内存区域内,以便于在命令执行过程中及时记录状态和错误信息。整个结构体的大小将按照 16 字节对齐。

hisi_sas_slot_buf_table

struct hisi_sas_slot_buf_table {
	struct hisi_sas_status_buffer status_buffer;
	union hisi_sas_command_table command_header;
	struct hisi_sas_sge_page sge_page;
};

这段代码定义了一个结构体 hisi_sas_slot_buf_table,用于在同一块内存区域内表示命令槽缓冲区。这个缓冲区用于存储命令的状态信息、命令头部以及相关的数据传输元素。

  • status_buffer:一个 hisi_sas_status_buffer 结构体,用于存储状态缓冲区,其中包括错误记录和信息单元。
  • command_header:一个联合体 hisi_sas_command_table,根据命令类型的不同,可以是 sspsmpstp 结构体的一种,用于存储命令头部。
  • sge_page:一个 hisi_sas_sge_page 结构体,用于存储数据传输元素,即散射/聚集列表(Scatter/Gather Elements)。

这个结构体的目的是将命令的状态信息、命令头部和数据传输元素存储在同一块内存区域内,以便于在命令执行过程中管理和传输命令的各个部分。整个结构体的大小可能会按照一定的对齐规则进行对齐。

hisi_sas_slot_dif_buf_table


struct hisi_sas_slot_dif_buf_table {
	struct hisi_sas_slot_buf_table slot_buf;
	struct hisi_sas_sge_dif_page sge_dif_page;
};

这段代码定义了一个结构体 hisi_sas_slot_dif_buf_table,它是在 hisi_sas_slot_buf_table 的基础上增加了数据完整性字段(DIF)的支持。该结构体用于表示命令槽缓冲区,包括状态信息、命令头部、散射/聚集列表(Scatter/Gather Elements,简称SGE)以及DIF数据传输元素。

  • slot_buf:一个 hisi_sas_slot_buf_table 结构体,用于存储命令的状态信息、命令头部和普通的SGE数据传输元素。
  • sge_dif_page:一个 hisi_sas_sge_dif_page 结构体,用于存储带有数据完整性字段(DIF)的SGE数据传输元素。

这个结构体的设计使得在DIF支持的情况下,可以将普通的数据传输元素与带有DIF的数据传输元素存储在同一块内存区域内,以便于在执行命令时进行管理和传输。整个结构体的大小可能会按照一定的对齐规则进行对齐。

extern function


extern struct scsi_transport_template *hisi_sas_stt;

extern bool hisi_sas_debugfs_enable;
extern u32 hisi_sas_debugfs_dump_count;
extern struct dentry *hisi_sas_debugfs_dir;

extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
extern int hisi_sas_alloc(struct hisi_hba *hisi_hba);
extern void hisi_sas_free(struct hisi_hba *hisi_hba);
extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis,
				int direction);
extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
extern void hisi_sas_sata_done(struct sas_task *task,
			    struct hisi_sas_slot *slot);
extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba);
extern int hisi_sas_probe(struct platform_device *pdev,
			  const struct hisi_sas_hw *ops);
extern void hisi_sas_remove(struct platform_device *pdev);

extern int hisi_sas_slave_configure(struct scsi_device *sdev);
extern int hisi_sas_slave_alloc(struct scsi_device *sdev);
extern int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time);
extern void hisi_sas_scan_start(struct Scsi_Host *shost);
extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
extern void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no,
				int enable);
extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy,
			      gfp_t gfp_flags);
extern void hisi_sas_phy_bcast(struct hisi_sas_phy *phy);
extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
				    struct sas_task *task,
				    struct hisi_sas_slot *slot,
				    bool need_lock);
extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
extern void hisi_sas_rst_work_handler(struct work_struct *work);
extern void hisi_sas_sync_rst_work_handler(struct work_struct *work);
extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no);
extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
				enum hisi_sas_phy_event event);
extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba);
extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max);
extern void hisi_sas_sync_cqs(struct hisi_hba *hisi_hba);
extern void hisi_sas_sync_poll_cqs(struct hisi_hba *hisi_hba);
extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba);
extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba);

这些是一些在 hisi_sas 驱动中定义的外部函数和变量的声明。这些函数和变量的作用在代码中的上下文中可能会有详细的注释说明。以下是每个声明的简要说明:

  1. extern struct scsi_transport_template *hisi_sas_stt;

    • 该变量是指向 scsi_transport_template 结构的指针,用于定义 hisi_sas 的SCSI传输模板。
  2. extern bool hisi_sas_debugfs_enable;

    • 一个布尔变量,用于标识是否启用调试文件系统支持。
  3. extern u32 hisi_sas_debugfs_dump_count;

    • 记录调试信息的转储次数。
  4. extern struct dentry *hisi_sas_debugfs_dir;

    • 指向调试文件系统的根目录。
  5. extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);

    • 停止所有物理通道(phy)的操作。当需要停止HBA上的所有物理通道时调用。
  6. extern int hisi_sas_alloc(struct hisi_hba *hisi_hba);

    • 分配并初始化 hisi_hba 结构以及相关资源,用于初始化HBA的数据结构。
  7. extern void hisi_sas_free(struct hisi_hba *hisi_hba);

    • 释放 hisi_hba 结构以及相关资源,用于释放HBA占用的资源。
  8. extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction);

    • 获取ATA协议类型,根据传输FIS中的信息判断是数据读取还是写入。
  9. extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);

    • asd_sas_port 结构转换为 hisi_sas_port 结构。
  10. extern void hisi_sas_sata_done(struct sas_task *task, struct hisi_sas_slot *slot);

    • 在SATA操作完成时被调用,用于处理SATA任务完成后的相关操作。
  11. extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba);

    • 获取HBA上固件的信息。
  12. extern int hisi_sas_probe(struct platform_device *pdev, const struct hisi_sas_hw *ops);

    • 驱动的探测函数,用于探测并初始化HBA硬件。
  13. extern void hisi_sas_remove(struct platform_device *pdev);

    • 驱动的移除函数,用于清理和释放探测过程中分配的资源。
  14. extern int hisi_sas_slave_configure(struct scsi_device *sdev);

    • 配置一个SCSI设备的SAS地址。
  15. extern int hisi_sas_slave_alloc(struct scsi_device *sdev);

    • 分配SCSI设备的资源,如slot等。
  16. extern int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time);

    • 在扫描完成时被调用,处理扫描完成后的相关操作。
  17. extern void hisi_sas_scan_start(struct Scsi_Host *shost);

    • 在开始扫描时被调用,用于初始化扫描过程。
  18. extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);

    • 执行HBA的重置操作,可能是软件重置或硬件重置。
  19. extern void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no, int enable);

    • 启用或禁用指定的物理通道(phy)。
  20. extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy, gfp_t gfp_flags);

    • 关闭指定的物理通道(phy),并进行相关处理。
  21. extern void hisi_sas_phy_bcast(struct hisi_sas_phy *phy);

    • 广播物理通道的事件。
  22. extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, struct hisi_sas_slot *slot, bool need_lock);

    • 释放SAS任务所需的相关资源。
  23. extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);

    • 初始化HBA的内存资源。
  24. extern void hisi_sas_rst_work_handler(struct work_struct *work);

    • HBA复位工作处理函数。
  25. extern void hisi_sas_sync_rst_work_handler(struct work_struct *work);

    • 同步HBA复位工作处理函数。
  26. extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no);

    • 物理通道(phy)准备就绪。
  27. extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy, enum hisi_sas_phy_event event);

    • 通知物理通道发生的事件。
  28. extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba);

    • 释放由HBA管理的所有任务。
  29. extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max);

    • 获取支

持的SAS链路速率掩码。

  1. extern void hisi_sas_sync_cqs(struct hisi_hba *hisi_hba);

    • 同步完成队列(completion queue)。
  2. extern void hisi_sas_sync_poll_cqs(struct hisi_hba *hisi_hba);

    • 同步轮询完成队列(poll completion queue)。
  3. extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba);

    • 准备进行控制器重置操作。
  4. extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba);

    • 完成控制器重置操作。

这些函数在 hisi_sas 驱动中扮演着不同的角色,用于管理HBA的初始化、任务处理、通道管理等各种操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值