前言
CXL 是一个比较新的技术,内核版本迭代太快,跟不上节奏,固定一个版本是不行了。
在阅读之前,希望读者能有一定的 PCIe/CXL 基础知识,精力有限,不能把所有知识点都能说的很详细,需要一定的基础才能理解,同时,希望在学习的过程中,手边能有 PCIe Spec 以及 CXL 2.0 /3.1 Spec,以便随时查看,当然,我也会尽量把重点的部分截图在博文中。
最后,如果有问题请留言讨论。
Ref
《PCI_Express_Base_5.0r1.0》
《CXL Specification_rev2p0_ver1p0_2020Oct26》
《CXL-3.1-Specification》
正文
Path: linux/drivers/cxl/core/memdev.c
1. devm_cxl_add_memdev()
struct cxl_memdev *devm_cxl_add_memdev(struct device *host,
struct cxl_dev_state *cxlds)
{
struct cxl_memdev *cxlmd;
struct device *dev;
struct cdev *cdev;
int rc;
cxlmd = cxl_memdev_alloc(cxlds, &cxl_memdev_fops);
// 申请内存并初始化 cxlmd
// device Obj 初始化
// 总线设置为 cxl_bus, 总线通过 cxl_driver->id 与 dev->type 进行匹配
// cdev_init 初始化,fops = cxl_memdev_fops, 文件系统创建相应文件
// 通过操作 open ioctl 等动作传输到驱动层处理
if (IS_ERR(cxlmd))
return cxlmd;
dev = &cxlmd->dev;
rc = dev_set_name(dev, "mem%d", cxlmd->id);
// cxlmd->id 通过 ida_alloc_max 分配
if (rc)
goto err;
/*
* Activate ioctl operations, no cxl_memdev_rwsem manipulation
* needed as this is ordered with cdev_add() publishing the device.
*/
cxlmd->cxlds = cxlds;
cxlds->cxlmd = cxlmd;
cdev = &cxlmd->cdev;
rc = cdev_device_add(cdev, dev);
// 创建字符设备驱动
if (rc)
goto err;
rc = devm_add_action_or_reset(host, cxl_memdev_unregister, cxlmd);
// 卸载操作
if (rc)
return ERR_PTR(rc);
return cxlmd;
err:
/*
* The cdev was briefly live, shutdown any ioctl operations that
* saw that state.
*/
cxl_memdev_shutdown(dev);
put_device(dev);
return ERR_PTR(rc);
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_memdev, CXL);
2. devm_cxl_setup_fw_upload()
设备驱动使用 firmware_upload_register
注册 FW upload, 参数中列出识别设备的名字,可以在文件系统中 /sys/class/firware 找到;
- 用户可以写 1 给
loading
发起一个 FW upload 操作; - 下一步,用户写 FW image 到
data
文件; - 写完之后,写 0 到
loading
文件,表示写完成,然后驱动就会使用cxl_memdev_fw_ops
提供的接口开始传输 FW;
FW upload 流程是 ops->prepare --》 ops->write --》 ops->poll_complete --》 ops->cleanup
The additional sysfs files are:
- status - provides an indication of the progress of a firmware update
- error - provides error information for a failed firmware update
- remaining_size - tracks the data transfer portion of an update
- cancel - echo 1 to this file to cancel the update
int devm_cxl_setup_fw_upload(struct device *host, struct cxl_memdev_state *mds)
{
struct cxl_dev_state *cxlds = &mds->cxlds;
struct device *dev = &cxlds->cxlmd->dev;
struct fw_upload *fwl;
if (!test_bit(CXL_MEM_COMMAND_ID_GET_FW_INFO, mds->enabled_cmds))
// 先看命令支不支持
return 0;
fwl = firmware_upload_register(THIS_MODULE, dev, dev_name(dev),
&cxl_memdev_fw_ops, mds);
// 注册
if (IS_ERR(fwl))
return PTR_ERR(fwl);
return devm_add_action_or_reset(host, cxl_remove_fw_upload, fwl);
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_fw_upload, CXL);