smmu学习笔记之streamtable 2

streamtable的另一种组织方式是linear,调用的是
static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
{
    void *strtab;
    u64 reg;
    u32 size;
    struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
    #计算size
    size = (1 << smmu->sid_bits) * (STRTAB_STE_DWORDS << 3);
    #申请memory
    strtab = dmam_alloc_coherent(smmu->dev, size, &cfg->strtab_dma,
                     GFP_KERNEL | __GFP_ZERO);
    if (!strtab) {
        dev_err(smmu->dev,
            "failed to allocate linear stream table (%u bytes)\n",
            size);
        return -ENOMEM;
    }
    cfg->strtab = strtab;
    cfg->num_l1_ents = 1 << smmu->sid_bits;

    /* Configure strtab_base_cfg for a linear table covering all SIDs */
    reg  = STRTAB_BASE_CFG_FMT_LINEAR;
    reg |= (smmu->sid_bits & STRTAB_BASE_CFG_LOG2SIZE_MASK)
        << STRTAB_BASE_CFG_LOG2SIZE_SHIFT;
    cfg->strtab_base_cfg = reg;

    arm_smmu_init_bypass_stes(strtab, cfg->num_l1_ents);
    return 0;
}
在arm_smmu_init_bypass_stes中会根据cfg->num_l1_ents 为最大值来逐一调用arm_smmu_write_strtab_ent
而这里的ste定义如下:可见valid和bypass都是true
    struct arm_smmu_strtab_ent ste = {
        .valid    = true,
        .bypass    = true,
    };
在arm_smmu_write_strtab_ent中主要是给strtab 赋值。最终调用arm_smmu_cmdq_issue_cmd 来发送CMDQ_OP_CFGI_STE 和 CMDQ_OP_PREFETCH_CFG命令。
static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
                    struct arm_smmu_cmdq_ent *ent)
{
    u64 cmd[CMDQ_ENT_DWORDS];
    unsigned long flags;
    bool wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV);
    struct arm_smmu_queue *q = &smmu->cmdq.q;

    if (arm_smmu_cmdq_build_cmd(cmd, ent)) {
        dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n",
             ent->opcode);
        return;
    }

    spin_lock_irqsave(&smmu->cmdq.lock, flags);
    while (queue_insert_raw(q, cmd) == -ENOSPC) {
        if (queue_poll_cons(q, false, wfe))
            dev_err_ratelimited(smmu->dev, "CMDQ timeout\n");
    }

    if (ent->opcode == CMDQ_OP_CMD_SYNC && queue_poll_cons(q, true, wfe))
        dev_err_ratelimited(smmu->dev, "CMD_SYNC timeout\n");
    spin_unlock_irqrestore(&smmu->cmdq.lock, flags);
}
从arm_smmu_cmdq_issue_cmd 中可以看到线根据arm_smmu_cmdq_ent->opcode的不同,bycase来对cmd赋值
然后将cmd插入到queue中,并通过queue_poll_cons 来查询是否执行插入成功
    while (queue_insert_raw(q, cmd) == -ENOSPC) {
        if (queue_poll_cons(q, false, wfe))
            dev_err_ratelimited(smmu->dev, "CMDQ timeout\n");
    }
特别的是如果ent->opcode == CMDQ_OP_CMD_SYNC的话,还要查询queue是否为null。
    if (ent->opcode == CMDQ_OP_CMD_SYNC && queue_poll_cons(q, true, wfe))
        dev_err_ratelimited(smmu->dev, "CMD_SYNC timeout\n");


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值