pci_init_capabilities的pci_msi_setup_pci_dev和pci_allocate_cap_save_buffers
来源:互联网 发布:知乎一句话自我介绍 编辑:程序博客网 时间:2024/05/21 14:48
pci_init_capabilities 中的pci_msi_setup_pci_dev初始化
static void pci_msi_setup_pci_dev(struct pci_dev *dev)
{
/*
* Disable the MSI hardware to avoid screaming interrupts
* during boot. This is the power on reset default so
* usually this should be a noop.
*/
dev->msi_cap = pci_find_capability(dev, PCI_CAP_ID_MSI);
if (dev->msi_cap)
pci_msi_set_enable(dev, 0);
dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
if (dev->msix_cap)
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
}
在pci_msi_setup_pci_dev 中首先通过pci_find_capability 来查询是否支持PCI_CAP_ID_MSI。如果支持的哈,调用pci_msi_set_enable disable掉
static inline void pci_msi_set_enable(struct pci_dev *dev, int enable)
{
u16 control;
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
control &= ~PCI_MSI_FLAGS_ENABLE;
if (enable)
control |= PCI_MSI_FLAGS_ENABLE;
pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
}
pci_msi_set_enable的实现比较简单,直接通过pci_read_config_word 来写寄存器,在pci子系统这边读写硬件都是通过pci_read_config_XXX 这样的接口进行,这个接口的第一个参数是dev,第二个是要写的位置,第三个就是要写的值.
通过判断是否支持PCI_CAP_ID_MSIX,如果支持的话,调用pci_msix_clear_and_set_ctrl 清零并enable
static inline void pci_msix_clear_and_set_ctrl(struct pci_dev *dev, u16 clear, u16 set)
{
u16 ctrl;
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl);
ctrl &= ~clear;
ctrl |= set;
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, ctrl);
}
pci_msix_clear_and_set_ctrl和pci_msi_set_enable的实现一样只是要写的寄存器的pos和值不一样.
pci_allocate_cap_save_buffers 中总共问五种capbility 预留buffer
void pci_allocate_cap_save_buffers(struct pci_dev *dev)
{
int error;
error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP,
PCI_EXP_SAVE_REGS * sizeof(u16));
if (error)
dev_err(&dev->dev,
"unable to preallocate PCI Express save buffer\n");
error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_PCIX, sizeof(u16));
if (error)
dev_err(&dev->dev,
"unable to preallocate PCI-X save buffer\n");
pci_allocate_vc_save_buffers(dev);
}
这五种capbility 分别是PCI_CAP_ID_EXP/PCI_CAP_ID_PCIX/PCI_EXT_CAP_ID_MFVC/PCI_EXT_CAP_ID_VC/PCI_EXT_CAP_ID_VC9
这里以PCI_CAP_ID_EXP 为例
int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size)
{
return _pci_add_cap_save_buffer(dev, cap, false, size);
}
static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
bool extended, unsigned int size)
{
int pos;
struct pci_cap_saved_state *save_state;
//首先查看是否有这个cap
if (extended)
pos = pci_find_ext_capability(dev, cap);
else
pos = pci_find_capability(dev, cap);
if (!pos)
return 0;
//申请一个struct pci_cap_saved_state *save_state;
save_state = kzalloc(sizeof(*save_state) + size, GFP_KERNEL);
if (!save_state)
return -ENOMEM;
save_state->cap.cap_nr = cap;
save_state->cap.cap_extended = extended;
save_state->cap.size = size;
//将save_state 添加到pci_dev->saved_cap_space
pci_add_saved_cap(dev, save_state);
return 0;
}
static void pci_add_saved_cap(struct pci_dev *pci_dev,
struct pci_cap_saved_state *new_cap)
{
hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space);
}
static void pci_msi_setup_pci_dev(struct pci_dev *dev)
{
/*
* Disable the MSI hardware to avoid screaming interrupts
* during boot. This is the power on reset default so
* usually this should be a noop.
*/
dev->msi_cap = pci_find_capability(dev, PCI_CAP_ID_MSI);
if (dev->msi_cap)
pci_msi_set_enable(dev, 0);
dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
if (dev->msix_cap)
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
}
在pci_msi_setup_pci_dev 中首先通过pci_find_capability 来查询是否支持PCI_CAP_ID_MSI。如果支持的哈,调用pci_msi_set_enable disable掉
static inline void pci_msi_set_enable(struct pci_dev *dev, int enable)
{
u16 control;
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
control &= ~PCI_MSI_FLAGS_ENABLE;
if (enable)
control |= PCI_MSI_FLAGS_ENABLE;
pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
}
pci_msi_set_enable的实现比较简单,直接通过pci_read_config_word 来写寄存器,在pci子系统这边读写硬件都是通过pci_read_config_XXX 这样的接口进行,这个接口的第一个参数是dev,第二个是要写的位置,第三个就是要写的值.
通过判断是否支持PCI_CAP_ID_MSIX,如果支持的话,调用pci_msix_clear_and_set_ctrl 清零并enable
static inline void pci_msix_clear_and_set_ctrl(struct pci_dev *dev, u16 clear, u16 set)
{
u16 ctrl;
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl);
ctrl &= ~clear;
ctrl |= set;
pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, ctrl);
}
pci_msix_clear_and_set_ctrl和pci_msi_set_enable的实现一样只是要写的寄存器的pos和值不一样.
pci_allocate_cap_save_buffers 中总共问五种capbility 预留buffer
void pci_allocate_cap_save_buffers(struct pci_dev *dev)
{
int error;
error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP,
PCI_EXP_SAVE_REGS * sizeof(u16));
if (error)
dev_err(&dev->dev,
"unable to preallocate PCI Express save buffer\n");
error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_PCIX, sizeof(u16));
if (error)
dev_err(&dev->dev,
"unable to preallocate PCI-X save buffer\n");
pci_allocate_vc_save_buffers(dev);
}
这五种capbility 分别是PCI_CAP_ID_EXP/PCI_CAP_ID_PCIX/PCI_EXT_CAP_ID_MFVC/PCI_EXT_CAP_ID_VC/PCI_EXT_CAP_ID_VC9
这里以PCI_CAP_ID_EXP 为例
int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size)
{
return _pci_add_cap_save_buffer(dev, cap, false, size);
}
static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
bool extended, unsigned int size)
{
int pos;
struct pci_cap_saved_state *save_state;
//首先查看是否有这个cap
if (extended)
pos = pci_find_ext_capability(dev, cap);
else
pos = pci_find_capability(dev, cap);
if (!pos)
return 0;
//申请一个struct pci_cap_saved_state *save_state;
save_state = kzalloc(sizeof(*save_state) + size, GFP_KERNEL);
if (!save_state)
return -ENOMEM;
save_state->cap.cap_nr = cap;
save_state->cap.cap_extended = extended;
save_state->cap.size = size;
//将save_state 添加到pci_dev->saved_cap_space
pci_add_saved_cap(dev, save_state);
return 0;
}
static void pci_add_saved_cap(struct pci_dev *pci_dev,
struct pci_cap_saved_state *new_cap)
{
hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space);
}
0 0
- pci_init_capabilities的pci_msi_setup_pci_dev和pci_allocate_cap_save_buffers
- pci_init_capabilities 中的pci_ea_init初始化
- 和和的区别
- & 和 &&、|和||的区别:
- ../和./和~/的含义
- &和&&、|和||的区别
- &&和&,||和|的区别
- &和&&、|和||的区别
- &和&&、|和||的区别
- ../和./和/的区别
- &和&&,|和||的区别
- |和||、&&和&的介绍
- "&"和"&&"、"|"和"||"的区别
- &和&& |和||的区别
- 和认同的认同和认同和
- 逻辑&和|和短路&&和||的区别
- java && 和 &、|| 和 | 的区别和作用
- C++中的.和::和:和->的区别
- Tomcat历史版本下载
- Linux2.6所有内核下载地址
- 深度学习Caffe案例
- GDB调试core文件详解
- redis存储和查询的java实现
- pci_init_capabilities的pci_msi_setup_pci_dev和pci_allocate_cap_save_buffers
- ZedBoard Vivado 自定义IP流水灯
- 智能指针 AutoPtr ScopedPtr SharedPtr
- Windows下的php代码上传到Linux出现换行符无法识别
- 对Core Foundation 与 Cocoa Foundation的理解
- android 线程池
- 程序断点(program breakpoint)和数据断点(data breakpoint)
- Python解析json到sql语句
- Jquery获取和修改img的src值的方法