首页 > 学院 > 开发设计 > 正文

smmu学习笔记之streamtable 2

2019-11-06 09:38:02
字体:
来源:转载
供稿:网友
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");
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表