PMC电源管理看门狗:iTCO_wdt

本文详细分析了iTCO_wdt在Linux系统中启动失败的问题,原因是内存资源与IPC资源冲突。通过研究内核驱动代码和器件手册,找到问题根源在于PMC的内存区域分配错误及RSM_RST_N脚的电路设计问题。修复软件代码并不能解决问题,最终因硬件限制放弃使用iTCO_wdt。
摘要由CSDN通过智能技术生成
  • 由 b178903294创建, 最后修改于9月 19, 2019   版权所有,谢绝转载

此看门狗相关寄存器位于PMC设备中,用于监控系统电源状态的。PMC (Power Management Controller) 是一个PCI device, pci地址为B/D/F=0/13/1,这个地址是IPC1/GCR/ACPI块的基地址。 关于pci地址如何计算出16进制物理地址请参照:PCI/PCIe基础——配置空间

近日接到需求,在系统log中看到iTCO_wdt在probe的过程中失败:

> [    9.377211] iTCO_wdt: Intel TCO WatchDog Timer Driver v1.11

> [    9.377407] iTCO_wdt: probe of iTCO_wdt failed with error -16

       所以第一时间就去看了是哪里打印出了这一条错误的log,后来经过测试发现是在iTCO_wdt probe的过程中申请相关寄存器没有成功,所以返回错误,具体是下面这段报错:

iTCO_wdt_probe

if (iTCO_wdt_private.iTCO_version >= 2) {

        iTCO_wdt_private.gcs_pmc_res = platform_get_resource(dev,

                            IORESOURCE_MEM,

                            ICH_RES_MEM_GCS_PMC);

 

        if (!iTCO_wdt_private.gcs_pmc_res)

            goto out;

 

        if (!request_mem_region(iTCO_wdt_private.gcs_pmc_res->start,          //这句由于申请没有被批准所以报错返回了

            resource_size(iTCO_wdt_private.gcs_pmc_res), dev->name)) {

            ret = -EBUSY;

            goto out;

        }

        iTCO_wdt_private.gcs_pmc = ioremap(iTCO_wdt_private.gcs_pmc_res->start,

            resource_size(iTCO_wdt_private.gcs_pmc_res));

        if (!iTCO_wdt_private.gcs_pmc) {

            ret = -EIO;

            goto unreg_gcs_pmc;

        }

    }

     request_mem_region的时候直接报错返回。那么肯定是这块内存申请不下来,那么这时候就去查了一下内存和谁冲突了??? 通过cat /proc/iomem 发现:

fe042000-fe043fff : INT34D2:00

   fe043000-fe043fff : iTCO_wdt

     原来是这两个内存段冲突了。那么问题来了我们的内存段是从哪里申请过来的???platform_get_resource这句函数就是申请相关资源用的,但是哪里定义了这些资源呢???经过艰苦卓绝的寻找,发现再intel_pmc_ipc.c中定义了相关资源:

static struct resource tco_res[] = {

    /* ACPI - TCO */

    {

        .flags = IORESOURCE_IO,

    },

    /* ACPI - SMI */

    {

        .flags = IORESOURCE_IO,

    },

    /* GCS */

    {

        .flags = IORESOURCE_MEM,

    },

};

     与iTCO_wdt相关的io和内存资源都在这里面定义了,具体是由下面这段代码添加的资源:

static int ipc_create_tco_device(void)

{

    struct platform_device *pdev;

    struct resource *res;

    int ret;

 

    pdev = platform_device_alloc(TCO_DEVICE_NAME, -1);

    if (!pdev) {

        dev_err(ipcdev.dev, "Failed to alloc tco platform device\n");

        return -ENOMEM;

    }

 

    pdev->dev.parent = ipcdev.dev;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值