การรีเซ็ตใน PCI Express นั้นซับซ้อนเล็กน้อย การรีเซ็ตมีสองประเภทหลัก - การรีเซ็ตแบบปกติและการรีเซ็ตระดับฟังก์ชั่น นอกจากนี้ยังมีการรีเซ็ตทั่วไปสองประเภทการรีเซ็ตพื้นฐานและรีเซ็ตที่ไม่ใช่พื้นฐาน ดูข้อกำหนด PCI Express สำหรับรายละเอียดทั้งหมด
'การรีเซ็ตแบบเย็น' คือการรีเซ็ตพื้นฐานที่เกิดขึ้นหลังจากใช้พลังงานกับอุปกรณ์ PCIe ดูเหมือนจะไม่มีวิธีมาตรฐานในการกระตุ้นการรีเซ็ตแบบเย็นบันทึกสำหรับการปิดระบบและเปิดใหม่อีกครั้ง บนเครื่องของฉัน/sys/bus/pci/slots
ไดเรกทอรีว่างเปล่า
'การรีเซ็ตแบบวอร์ม' เป็นการรีเซ็ตพื้นฐานที่ทำงานโดยไม่ตัดการเชื่อมต่อพลังงานจากอุปกรณ์ ดูเหมือนจะไม่มีวิธีมาตรฐานในการทำให้เกิดการรีเซ็ตแบบวอร์ม
'การรีเซ็ตร้อน' คือการรีเซ็ตแบบเดิมที่เรียกใช้ผ่านลิงก์ PCI Express การรีเซ็ตร้อนจะถูกเรียกใช้เมื่อลิงก์ถูกบังคับให้อยู่ในสถานะไม่ใช้งานไฟฟ้าหรือโดยการส่งชุดที่สั่งซื้อ TS1 และ TS2 ด้วยชุดบิตรีเซ็ตร้อน ซอฟต์แวร์สามารถเริ่มต้นการรีเซ็ตร้อนโดยการตั้งค่าแล้วล้างบิตรีเซ็ตบัสรองในการลงทะเบียนตัวควบคุมบริดจ์ในพื้นที่กำหนดค่า PCI ของบริดจ์พอร์ตอัพสตรีมของอุปกรณ์
'รีเซ็ตระดับฟังก์ชั่น' (FLR) เป็นการรีเซ็ตที่ส่งผลกระทบต่อฟังก์ชั่นเดียวของอุปกรณ์ PCI Express ต้องไม่รีเซ็ตอุปกรณ์ PCIe ทั้งหมด การใช้การรีเซ็ตระดับฟังก์ชั่นนั้นไม่จำเป็นต้องใช้กับข้อกำหนด PCIe การรีเซ็ตระดับฟังก์ชั่นเริ่มต้นโดยการตั้งค่าบิตเริ่มต้นระดับฟังก์ชันในการลงทะเบียนการควบคุมอุปกรณ์ของฟังก์ชั่นในโครงสร้างความสามารถของ PCI Express ในพื้นที่กำหนดค่า PCI
ลินุกซ์ exposes /sys/bus/pci/devices/$dev/reset
ฟังก์ชั่นการตั้งค่าฟังก์ชั่นระดับในรูปแบบของ การเขียน 1 ไปยังไฟล์นี้จะเริ่มต้นการรีเซ็ตระดับฟังก์ชั่นในฟังก์ชั่นที่เกี่ยวข้อง โปรดทราบว่าสิ่งนี้มีผลเฉพาะกับฟังก์ชั่นเฉพาะของอุปกรณ์ไม่ใช่ทั้งอุปกรณ์และอุปกรณ์ไม่จำเป็นต้องใช้การรีเซ็ตระดับฟังก์ชั่นตามข้อกำหนด PCIe
ฉันไม่ได้ตระหนักถึงวิธี 'ดี' ใด ๆ สำหรับการเรียกใช้การรีเซ็ตร้อน (ไม่มีรายการ sysfs สำหรับที่) อย่างไรก็ตามมันเป็นไปได้ที่จะใช้ setpci ทำเช่นนั้น:
#!/bin/bash
dev=$1
if [ -z "$dev" ]; then
echo "Error: no device specified"
exit 1
fi
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
dev="0000:$dev"
fi
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
echo "Error: device $dev not found"
exit 1
fi
port=$(basename $(dirname $(readlink "/sys/bus/pci/devices/$dev")))
if [ ! -e "/sys/bus/pci/devices/$port" ]; then
echo "Error: device $port not found"
exit 1
fi
echo "Removing $dev..."
echo 1 > "/sys/bus/pci/devices/$dev/remove"
echo "Performing hot reset of port $port..."
bc=$(setpci -s $port BRIDGE_CONTROL)
echo "Bridge control:" $bc
setpci -s $port BRIDGE_CONTROL=$(printf "%04x" $(("0x$bc" | 0x40)))
sleep 0.01
setpci -s $port BRIDGE_CONTROL=$bc
sleep 0.5
echo "Rescanning bus..."
echo 1 > "/sys/bus/pci/devices/$port/rescan"
ตรวจสอบให้แน่ใจว่าไม่มีการโหลดไดรเวอร์ที่แนบมาทั้งหมดก่อนที่จะเรียกใช้สคริปต์นี้ สคริปต์นี้จะพยายามที่จะลบอุปกรณ์ PCIe จากนั้นคำสั่งพอร์ตสวิตช์อัปสตรีมเพื่อออกการรีเซ็ตร้อนจากนั้นลองสแกนบัส PCIe อีกครั้ง สคริปต์นี้ยังได้รับการทดสอบบนอุปกรณ์ที่มีฟังก์ชั่นเดียวเท่านั้นดังนั้นจึงอาจต้องมีการทำงานซ้ำสำหรับอุปกรณ์ที่มีฟังก์ชั่นหลายอย่าง
reboot -f
ไหม คล้ายกับการกดปุ่มเปิดปิดของ CPU