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);
}




0 0
原创粉丝点击