PCIe学习笔记(1)Hot-Plug机制

文章目录

  • Hot-Plug Init
  • Hot Add Flow
  • Surprise Remove Flow
  • NPEM Flow

Hot-Plug Init

PCIe hot-plug是一种支持在不关机情况下从支持的插槽添加或删除设备的功能,PCIe架构定义了一些寄存器以支持原生热插拔。相关寄存器主要分布在Device Capabilities, Slot Capabilities, Slot Control, Slot Status和Slot Capabilities 2。Hot-Plug相关支持寄存器位置如下。
在这里插入图片描述
一个Downstream Port支持以下热插拔事件。

  • Slot Events:
    • Attention Button Pressed
    • Power Fault Detected
    • MRL Sensor Changed
    • Presence Detect Changed
  • Command Completed Events
  • Data Link Layer State Changed Events

主要事件都可以通过寄存器控制使能,需要在初始化时配置启用。如果要启用INTx message,需配置如下:

  • Command register内的Interrupt Disable位需要设为0
  • Slot Control register内的Hot-Plug Interrupt Enable位需要设为1
  • 至少使能一个hot-plug event控制寄存器
    如果要启用MSI/MSI-X,则需取消屏蔽关联向量。PME和Hot-Plug事件中断共享同一向量,由PCIE Capabilities的Interrupt Message Number域段控制。
    在这里插入图片描述

Hot-Plug事件产生需要启用PME_En位。
在这里插入图片描述

Hot Add Flow

主要处理Presence Detect Changed, Command Completed events(需要在No Command Completed Support为0时,否则硬件支持无通知式自动完成)。
pciehp_handle_presence_or_link_change函数为Presence Detect Changed事件中断服务函数。

void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
{int present, link_active;/** If the slot is on and presence or link has changed, turn it off.* Even if it's occupied again, we cannot assume the card is the same.*/mutex_lock(&ctrl->state_lock);switch (ctrl->state) {case BLINKINGOFF_STATE:cancel_delayed_work(&ctrl->button_work);fallthrough;case ON_STATE:ctrl->state = POWEROFF_STATE;mutex_unlock(&ctrl->state_lock);if (events & PCI_EXP_SLTSTA_DLLSC)ctrl_info(ctrl, "Slot(%s): Link Down\n",slot_name(ctrl));if (events & PCI_EXP_SLTSTA_PDC)ctrl_info(ctrl, "Slot(%s): Card not present\n",slot_name(ctrl));pciehp_disable_slot(ctrl, SURPRISE_REMOVAL);  //call remove_boardbreak;default:mutex_unlock(&ctrl->state_lock);break;}/* Turn the slot on if it's occupied or link is up */mutex_lock(&ctrl->state_lock);present = pciehp_card_present(ctrl);link_active = pciehp_check_link_active(ctrl);if (present <= 0 && link_active <= 0) {if (ctrl->state == BLINKINGON_STATE) {ctrl->state = OFF_STATE;cancel_delayed_work(&ctrl->button_work);pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,INDICATOR_NOOP);ctrl_info(ctrl, "Slot(%s): Card not present\n",slot_name(ctrl));}mutex_unlock(&ctrl->state_lock);return;}switch (ctrl->state) {case BLINKINGON_STATE:cancel_delayed_work(&ctrl->button_work);fallthrough;case OFF_STATE:ctrl->state = POWERON_STATE;mutex_unlock(&ctrl->state_lock);if (present)ctrl_info(ctrl, "Slot(%s): Card present\n",slot_name(ctrl));if (link_active)ctrl_info(ctrl, "Slot(%s): Link Up\n",slot_name(ctrl));ctrl->request_result = pciehp_enable_slot(ctrl);  //call board_added()break;default:mutex_unlock(&ctrl->state_lock);break;}
}
pciehp_enable_slot会调用board_added(通过__pciehp_enable_slot)和pciehp_set_indicators
static int pciehp_enable_slot(struct controller *ctrl)
{int ret;pm_runtime_get_sync(&ctrl->pcie->port->dev);ret = __pciehp_enable_slot(ctrl);if (ret && ATTN_BUTTN(ctrl))/* may be blinking */pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,INDICATOR_NOOP);pm_runtime_put(&ctrl->pcie->port->dev);mutex_lock(&ctrl->state_lock);ctrl->state = ret ? OFF_STATE : ON_STATE;mutex_unlock(&ctrl->state_lock);return ret;
}

board_added完成了pciehp_power_on_slot,pciehp_set_indicators,pciehp_configure_device (Off -> Blink -> On)

static int board_added(struct controller *ctrl)
{int retval = 0;struct pci_bus *parent = ctrl->pcie->port->subordinate;if (POWER_CTRL(ctrl)) {/* Power on slot */retval = pciehp_power_on_slot(ctrl);if (retval)return retval;}pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK,INDICATOR_NOOP);/* Check link training status */retval = pciehp_check_link_status(ctrl);if (retval)goto err_exit;/* Check for a power fault */if (ctrl->power_fault_detected || pciehp_query_power_fault(ctrl)) {ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl));retval = -EIO;goto err_exit;}retval = pciehp_configure_device(ctrl);if (retval) {if (retval != -EEXIST) {ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",pci_domain_nr(parent), parent->number);goto err_exit;}}pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON,PCI_EXP_SLTCTL_ATTN_IND_OFF);return 0;err_exit:set_slot_off(ctrl);return retval;
}
int pciehp_power_on_slot(struct controller *ctrl)
{struct pci_dev *pdev = ctrl_dev(ctrl);u16 slot_status;int retval;/* Clear power-fault bit from previous power failures */pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);if (slot_status & PCI_EXP_SLTSTA_PFD)pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,PCI_EXP_SLTSTA_PFD);ctrl->power_fault_detected = 0;pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_ON, PCI_EXP_SLTCTL_PCC);ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,PCI_EXP_SLTCTL_PWR_ON);retval = pciehp_link_enable(ctrl);if (retval)ctrl_err(ctrl, "%s: Can not enable the link!\n", __func__);return retval;
}

Surprise Remove Flow

需要处理AER和DPC events,然后处理hot-plug events。中断触发pciehp_handle_presence_or_link_change,然后pciehp_disable_slot会调用remove_board(通过__pciehp_disable_slot),remove_board主要完成pciehp_power_off_slot和pciehp_set_indicators (On -> Off)。Presense detected需要等待DPC先触发。

static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal)
{int ret;pm_runtime_get_sync(&ctrl->pcie->port->dev);ret = __pciehp_disable_slot(ctrl, safe_removal);pm_runtime_put(&ctrl->pcie->port->dev);mutex_lock(&ctrl->state_lock);ctrl->state = OFF_STATE;mutex_unlock(&ctrl->state_lock);return ret;
}
static void remove_board(struct controller *ctrl, bool safe_removal)
{pciehp_unconfigure_device(ctrl, safe_removal);if (POWER_CTRL(ctrl)) {pciehp_power_off_slot(ctrl);/** After turning power off, we must wait for at least 1 second* before taking any action that relies on power having been* removed from the slot/adapter.*/msleep(1000);/* Ignore link or presence changes caused by power off */atomic_and(~(PCI_EXP_SLTSTA_DLLSC | PCI_EXP_SLTSTA_PDC),&ctrl->pending_events);}pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,INDICATOR_NOOP);
}
void pciehp_power_off_slot(struct controller *ctrl)
{pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC);ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,PCI_EXP_SLTCTL_PWR_OFF);
}

NPEM Flow

NPEM(Native PCIe Enclosure Management) 是PCIe标准为NVMe设备定义的扩展LED控制功能,热插拔的LED控制机制由NPEM完成。可以实现在DP内或UP内,用于控制和更新LED状态。软件通过写入NPEM控制寄存器来发出NPEM指令,NPEM控制器根据指令更新LED状态,并使用completed机制指示软件完成。
在这里插入图片描述
NPEM支持实现OK/Locate/Fail/Rebuild等可选LED状态。
在这里插入图片描述
Linux Reference:
drivers/pci/hotplug /pciehp_hpc.c
driversdrivers/pci/hotplug/pciehp_ctrl.c

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/674360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站被攻击有什么办法呢?

最近&#xff0c;德迅云安全遇到不少网站用户遇到攻击问题&#xff0c;来咨询安全解决方案。目前在所有的网络攻击方式中&#xff0c;DDoS是最常见&#xff0c;也是最高频的攻击方式之一。不少用户网站上线后&#xff0c;经常会遭受到攻击的困扰。有些攻击持续时间比较短影响较…

MCU+SFU视频会议一体化,视频监控,指挥调度(AR远程协助)媒体中心解决方案。

视频互动应用已经是政务和协同办公必备系统&#xff0c;早期的分模块&#xff0c;分散的视频应该不能满足业务需要&#xff0c;需要把视频监控&#xff0c;会议&#xff0c;录存一体把视频资源整合起来&#xff0c;根据客户需求&#xff0c;需要能够多方视频互动&#xff0c;直…

cmake安装LAMMPS增加MOLECULE等package

使用cmake可以较make更加快捷的安装LAMMPS,关于官网上已有Cmake安装的详细教程&#xff1a; https://docs.lammps.org/Build_cmake.html 可是经过使用&#xff0c;发现默认的安装方式里只有最基础的包&#xff0c;甚至没有MOLECULE包 因此为了使用cmake来增加想要安装的包&a…

代码随想录算法训练营第29天|491.递增子序列 * * 46.全排列 * 47.全排列 II

文章目录 491.递增子序列思路&#xff1a;代码 思路&#xff1a;优化代码&#xff1a; 46.全排列思路代码一&#xff1a;使用used数组代码二&#xff1a;使用path判断元素 47.全排列 II思路一&#xff1a;层节点和路径都是用used数组做记录思路二&#xff1a;层通过排序后是否重…

学习Vue3的第一天

目录 简介 什么是 Vue&#xff1f; 创建Vue3工程 前提条件 基于 vue-cli 创建&#xff08;不推荐&#xff09; 基于 vite 创建&#xff08;推荐&#xff09; 通过 CDN 使用 Vue 代码示例 简介 什么是 Vue&#xff1f; Vue.js 是一个流行的前端 JavaScript 框架&#…

c# DataTable 帮助类

public class DataTableHelper { #region DataTable转IList /// <summary> /// DataTable转IList集合 /// </summary> /// <typeparam name"T"></typeparam> /// <param name"dataTabl…

linux查看公网地址

curl ifconfig.mewget -qO- ifconfig.me

用keytool 生成JWT的RSA非对称密钥

写在前面 JWT 令牌 可以由 X.509 证书或 256 位非对称密钥签名来充当&#xff0c;为了获得合法的JWT 令牌&#xff0c;我们可以使用JDK中的keytool.exe工具来生成。 本例的操作环境是Windows系统&#xff0c;操作的前置条件需要先安装好JDK&#xff0c;并配置好环境变量&…

C#的Char 结构的像IsLetterOrDigit(Char)等常见的方法

目录 一、Char 结构的方法 二、Char.IsLetterOrDigit 方法 1.Char.IsLetterOrDigit(Char)用法 2.IsLetterOrDigit(String, Int32)方法 三、Char.IsLetter 方法 1.IsLetter(Char) 2.IsLetter(String, Int32) 四、Char.IsDigit 方法 1. IsDigit(String, Int32) 2.IsDig…

Vue 学习随笔系列九 -- 表格中插入图片、背景、自定义表头

表格中插入图片和icon 文章目录 表格中插入图片和icon一、如何插入图片1、代码2、效果 二、文字添加背景1、代码2、效果 三、表头悬浮提示语四、表头添加图标 一、如何插入图片 1、代码 <template><div><el-tablesize"small"borderv-loading"l…

K8S部署Harbor镜像仓库(含离线安装包harbor-offline-installer国内下载链接)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

互联网摸鱼日报(2024-02-05)

互联网摸鱼日报(2024-02-05) 博客园新闻 巨人网络大模型GiantGPT完成备案 有传闻称京东紧急制定主播招聘计划 不考核GMV和毛利等 实测百度文心一言APP生成“专属数字分身”免费功能 小米要退出印度笔记本市场&#xff1f;产品均售罄、官网导航条移除相关栏目 高德、百度地…

面向智算服务,构建可观测体系最佳实践

作者&#xff1a;蓟北 构建面向 AI、大数据、容器的可观测体系 &#xff08;一&#xff09;智算服务可观测概况 对于越来越火爆的人工智能领域来说&#xff0c;MLOps 是解决这一领域的系统工程&#xff0c;它结合了所有与机器学习相关的任务和流程&#xff0c;从数据管理、建…

Qt程序设计-读写CSV文件

本文实例演示Qt读写CSV文件实现 创建项目 添加两个按钮和一个显示路径的label 界面如下 UI界面 <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"><class>MainWindow</class><widget class="QM…

[BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析

保护 ida 这里使用mmap函数创造了一个内存映射区域 从地址0x123000开始&#xff0c;大小位0x1000 权限为可写可执行&#xff08;可读0x1&#xff0c;可写0x2&#xff0c;可执行0x3&#xff09; 设置为私有映射&#xff08;MAP_PRIVATE&#xff09;和匿名映射&#xff08;MAP…

【buuctf--被偷走的文件】

将 ftp 流量过滤下来&#xff0c;追踪 ftp 流量&#xff0c;得到下图 先解释一下这四行什么意思&#xff1a; PASV&#xff1a; 这是FTP的命令&#xff0c;用于告知服务器在数据连接中使用被动模式&#xff08;Passive Mode&#xff09;。在被动模式下&#xff0c;数据连接的…

Java Stram 流对于返回对象的处理 (结束流)

Java Stram 流对于返回对象的处理 &#xff08;结束流&#xff09; package com.zhong.streamdemo.showdownstreamdemo;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.util.*; import java.util.stream.Collectors; im…

【golang】24、go get 和 go mod:indrect 与 go mod tidy

文章目录 go get 会执行如下操作&#xff1a; 操作 go.mod 文件&#xff08;add、update、remove&#xff09;下载依赖到 $GOPATH/pkg/mod 中若已安装&#xff0c;则更新该包&#xff0c;到最新版本 试验前置准备&#xff1a;首先删除已下载的依赖&#xff0c;rm -rf $GOPATH…

MySQL篇----第十四篇

系列文章目录 文章目录 系列文章目录前言一、MySQL 数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?二、锁的优化策略三、索引的底层实现原理和优化四、什么情况下设置了索引但无法使用前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽…

OpenId、UnionId

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1. OpenId1.1 概念1.2 公众号OpenId&#xff08;简称 wxopenid&#xff09;同一个微信用户在小程序和公众号上的openid是不同的 1.3 openid的获取方式方式1. 调用wx…