2017-11-03 7 views
1

openwrt用のPCIEデバイスドライバを開発していますが、last questionで述べたタイマ割り込みでioメモリにアクセスしようとするとデータバスエラーが発生しました。多くの研究の後、私はその理由を知ったかもしれないと思うが、私はそれを解決することができない。私の悩みは以下の通りです。PCIE領域が一貫しておらず、一貫していません

先週、私はpcie領域のサイズがシステムの起動時に変更されている可能性があることを知りました。私のドライバではbar0の領域サイズは4096(pci_resource_lenから返されます)であり、領域サイズは4097でlspci -vvで、これはLinuxカーネルのページサイズを壊します。 pciutilのソースコードを読むと、lspciコマンドが/sys/devices/pci0000:00/0000:00:00.0/resouceファイルからpcie情報を取得することが分かります。だから私はすべての私のカスタムコンポーネントを削除し、私のルータ上で元のopenwrtを実行します。 cat /sys/devices/pci0000:00/0000:00:00.0/resouceによって、結果(BAR0)の最初の行は

0x0000000010008000 0x0000000010009000 0x0000000000040200 

また、私も/proc/iomemの内容を確認し、PCIEに関連するコンテンツが

10000000-13ffffff : mem_base 
    10000000-13ffffff : PCI memory space 
     10000000-10007fff : 0000:00:00.0 
     10008000-10008fff : 0000:00:00.0 

それはスーパー奇妙です上記の2つのファイルが示すbar0の領域サイズは異なります。 PCIEのメカニズムによれば、領域サイズは常に2の累乗でなければなりません。領域サイズはどのようにして4097になりますか?

答えて

0

Linuxカーネルのソースコードを読んで数週間を過ごした後、これはLinuxカーネル4.4.14のバグであることがわかりました。

/sys/devices/pci0000:00/0000:00:00.0/resouceの内容は、ファイルdrivers/pci/pci-sysfs.cの機能resource_showによって生成されます。関連するコードは

for (i = 0; i < max; i++) { 
    struct resource *res = &pci_dev->resource[i]; 
    pci_resource_to_user(pci_dev, i, res, &start, &end); 
    str += sprintf(str, "0x%016llx 0x%016llx 0x%016llx\n", 
       (unsigned long long)start, 
       (unsigned long long)end, 
       (unsigned long long)res->flags); 
} 

実際

static inline void pci_resource_to_user(const struct pci_dev *dev, int bar, 
     const struct resource *rsrc, resource_size_t *start, 
     resource_size_t *end) 
{ 
    phys_addr_t size = resource_size(rsrc); 

    *start = fixup_bigphys_addr(rsrc->start, size); 
    *end = rsrc->start + size; 
} 
arch/mips/include/asm/pci.hに位置して呼び出される関数 pci_resource_to_userある

*endの計算が間違っていると

*end = rsrc->start + size - (size ? 1 : 0) 
で置き換えるべきです
関連する問題