Linux

如何調試無法綁定到 Linux 上的設備的驅動程序?

  • September 23, 2017

我試圖弄清楚為什麼以下設備未在我的Creator CI20上設置為其驅動程序。作為參考,我使用的是 Linux 核心 v4.13.0 並在本地進行編譯:

make ARCH=mips ci20_defconfig
make -j8 ARCH=mips CROSS_COMPILE=mipsel-linux-gnu- uImage

從正在執行的系統中我可以看到:

ci20@ci20:~# find /sys | grep rng
/sys/firmware/devicetree/base/jz4780-cgu@10000000/rng@d8
/sys/firmware/devicetree/base/jz4780-cgu@10000000/rng@d8/compatible
/sys/firmware/devicetree/base/jz4780-cgu@10000000/rng@d8/name
/sys/bus/platform/drivers/jz4780-rng
/sys/bus/platform/drivers/jz4780-rng/bind
/sys/bus/platform/drivers/jz4780-rng/unbind
/sys/bus/platform/drivers/jz4780-rng/uevent

所以核心在執行時可以看到設備,現在缺少的部分是為什麼驅動程序永遠不會綁定?我會期待這樣的事情:

/sys/bus/platform/drivers/jz4780-rng/100000d8.rng

我確實找到了其他一些解釋如何調試正在執行的系統的文章,例如:

雖然這些文章上的資訊是準確的,但對我來說並不是很有幫助。由於我在本地建構我的核心(我printk在驅動程序的探測功能中添加了jz4780-rng),我的問題是:

  • **我應該在編譯時打開什麼選項,**以便核心列印關於未能為jz4780-rng驅動程序呼叫探測函式的準確資訊?
  • 特別是如何列印測試匯流排/驅動程序的完整列表driver_probe_device

printk可以在程式碼中的任何地方添加來調試它。問題是:哪個函式正在遍歷設備樹並呼叫探測/初始化函式?

以供參考:

$ dtc -I fs -O dts /sys/firmware/devicetree/base | grep -A 1 rng
             rng@d8 {
                     compatible = "ingenic,jz4780-rng";
             };

兼容字元串聲明為:

cgu: jz4780-cgu@10000000 {
   compatible = "ingenic,jz4780-cgu", "syscon";
   reg = <0x10000000 0x100>;

   clocks = <&ext>, <&rtc>;
   clock-names = "ext", "rtc";

   #clock-cells = <1>;

   rng: rng@d8 {
       compatible = "ingenic,jz4780-rng";
   };
};

在驅動程序中為:

static const struct of_device_id jz4780_rng_dt_match[] = {
   {
       .compatible = "ingenic,jz4780-rng",
   },
   { },
};
MODULE_DEVICE_TABLE(of, jz4780_rng_dt_match);

static struct platform_driver jz4780_rng_driver = {
   .driver     = {
       .name   = "jz4780-rng",
       .of_match_table = jz4780_rng_dt_match,
   },
   .probe      = jz4780_rng_probe,
   .remove     = jz4780_rng_remove,
};
module_platform_driver(jz4780_rng_driver);

更新1:

當我用 建構我的核心時CONFIG_DEBUG_DRIVER=y,我可以看到以下內容:

# grep driver_probe_device syslog
Sep  6 10:08:07 ci20 kernel: [    0.098280] bus: 'platform': driver_probe_device: matched device 10031000.serial with driver ingenic-uart
Sep  6 10:08:07 ci20 kernel: [    0.098742] bus: 'platform': driver_probe_device: matched device 10033000.serial with driver ingenic-uart
Sep  6 10:08:07 ci20 kernel: [    0.099209] bus: 'platform': driver_probe_device: matched device 10034000.serial with driver ingenic-uart
Sep  6 10:08:07 ci20 kernel: [    0.106945] bus: 'platform': driver_probe_device: matched device 1b000000.nand-controller with driver jz4780-nand
Sep  6 10:08:07 ci20 kernel: [    0.107282] bus: 'platform': driver_probe_device: matched device 134d0000.bch with driver jz4780-bch
Sep  6 10:08:07 ci20 kernel: [    0.107470] bus: 'platform': driver_probe_device: matched device 16000000.dm9000 with driver dm9000
Sep  6 10:08:07 ci20 kernel: [    0.165618] bus: 'platform': driver_probe_device: matched device 10003000.rtc with driver jz4740-rtc
Sep  6 10:08:07 ci20 kernel: [    0.166177] bus: 'platform': driver_probe_device: matched device 10002000.jz4780-watchdog with driver jz4740-wdt
Sep  6 10:08:07 ci20 kernel: [    0.170930] bus: 'platform': driver_probe_device: matched device 1b000000.nand-controller with driver jz4780-nand

但只有:

# grep rng syslog
Sep  6 10:08:07 ci20 kernel: [    0.166842] bus: 'platform': add driver jz4780-rng
Sep  6 10:08:42 ci20 kernel: [   54.584451] random: crng init done

作為旁注,rng頂級節點:cgu此處未引用,但有一個jz4780-cgu驅動程序。


更新2:

如果我將rng節點聲明移到頂層cgu節點之外,我至少可以看到最後發生了一些綁定:

# grep rng /var/log/syslog 
Sep  6 10:30:57 ci20 kernel: [    0.167017] bus: 'platform': add driver jz4780-rng
Sep  6 10:30:57 ci20 kernel: [    0.167033] bus: 'platform': driver_probe_device: matched device 10000000.rng with driver jz4780-rng
Sep  6 10:30:57 ci20 kernel: [    0.167038] bus: 'platform': really_probe: probing driver jz4780-rng with device 10000000.rng
Sep  6 10:30:57 ci20 kernel: [    0.167050] jz4780-rng 10000000.rng: no pinctrl handle
Sep  6 10:30:57 ci20 kernel: [    0.167066] devices_kset: Moving 10000000.rng to end of list
Sep  6 10:30:57 ci20 kernel: [    0.172774] jz4780-rng: probe of 10000000.rng failed with error -22
Sep  6 10:31:32 ci20 kernel: [   54.802794] random: crng init done

使用:

   rng: rng@100000d8 {
       compatible = "ingenic,jz4780-rng";
   };

我還可以驗證:

# find /sys/ | grep rng
/sys/devices/platform/10000000.rng
/sys/devices/platform/10000000.rng/subsystem
/sys/devices/platform/10000000.rng/driver_override
/sys/devices/platform/10000000.rng/modalias
/sys/devices/platform/10000000.rng/uevent
/sys/devices/platform/10000000.rng/of_node
/sys/firmware/devicetree/base/rng@100000d8
/sys/firmware/devicetree/base/rng@100000d8/compatible
/sys/firmware/devicetree/base/rng@100000d8/status
/sys/firmware/devicetree/base/rng@100000d8/reg
/sys/firmware/devicetree/base/rng@100000d8/name
/sys/bus/platform/devices/10000000.rng
/sys/bus/platform/drivers/jz4780-rng
/sys/bus/platform/drivers/jz4780-rng/bind
/sys/bus/platform/drivers/jz4780-rng/unbind
/sys/bus/platform/drivers/jz4780-rng/uevent

使驅動程序綁定到設備的有效解決方案是:

cgublock: jz4780-cgublock@10000000 {
   compatible = "simple-bus", "syscon";

   #address-cells = <1>;
   #size-cells = <1>;

   reg = <0x10000000 0x100>;
   ranges;

   cgu: jz4780-cgu@10000000 {
       compatible = "ingenic,jz4780-cgu";
       reg = <0x10000000 0x100>;

       clocks = <&ext>, <&rtc>;
       clock-names = "ext", "rtc";

       #clock-cells = <1>;
   };

   rng: rng@d8 {
       compatible = "ingenic,jz4780-rng";
       reg = <0x100000d8 0x8>;
   };
};

這是通過查看其他範例發現的。我更喜歡一個解決方案,讓我得到正確的診斷,為什麼之前的嘗試是不正確的。

引用自:https://unix.stackexchange.com/questions/390647