pci

    xiaoxiao2021-04-17  47

    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); }
    转载请注明原文地址: https://ju.6miu.com/read-674166.html

    最新回复(0)