On 24/07/2019 13:15, Will Deacon wrote:
Hi John,

Thanks for reading the code!

On Fri, Jul 19, 2019 at 12:04:15PM +0100, John Garry wrote:
+static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
+                                      u64 *cmds, int n, bool sync)
+{
+       u64 cmd_sync[CMDQ_ENT_DWORDS];
+       u32 prod;
        unsigned long flags;
-       bool wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV);
-       struct arm_smmu_cmdq_ent ent = { .opcode = CMDQ_OP_CMD_SYNC };
-       int ret;
+       bool owner;
+       struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+       struct arm_smmu_ll_queue llq = {
+               .max_n_shift = cmdq->q.llq.max_n_shift,
+       }, head = llq;
+       int ret = 0;

-       arm_smmu_cmdq_build_cmd(cmd, &ent);
+       /* 1. Allocate some space in the queue */
+       local_irq_save(flags);
+       llq.val = READ_ONCE(cmdq->q.llq.val);
+       do {
+               u64 old;
+
+               while (!queue_has_space(&llq, n + sync)) {
+                       local_irq_restore(flags);
+                       if (arm_smmu_cmdq_poll_until_not_full(smmu, &llq))
+                               dev_err_ratelimited(smmu->dev, "CMDQ 
timeout\n");
+                       local_irq_save(flags);
+               }
+
+               head.cons = llq.cons;
+               head.prod = queue_inc_prod_n(&llq, n + sync) |
+                                            CMDQ_PROD_OWNED_FLAG;
+
+               old = cmpxchg_relaxed(&cmdq->q.llq.val, llq.val, head.val);
+               if (old == llq.val)
+                       break;
+
+               llq.val = old;
+       } while (1);
+       owner = !(llq.prod & CMDQ_PROD_OWNED_FLAG);
+
+       /*
+        * 2. Write our commands into the queue
+        * Dependency ordering from the cmpxchg() loop above.
+        */
+       arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n);
+       if (sync) {
+               prod = queue_inc_prod_n(&llq, n);
+               arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod);
+               queue_write(Q_ENT(&cmdq->q, prod), cmd_sync, CMDQ_ENT_DWORDS);
+
+               /*
+                * In order to determine completion of our CMD_SYNC, we must
+                * ensure that the queue can't wrap twice without us noticing.
+                * We achieve that by taking the cmdq lock as shared before
+                * marking our slot as valid.
+                */
+               arm_smmu_cmdq_shared_lock(cmdq);
+       }
+
+       /* 3. Mark our slots as valid, ensuring commands are visible first */
+       dma_wmb();
+       prod = queue_inc_prod_n(&llq, n + sync);
+       arm_smmu_cmdq_set_valid_map(cmdq, llq.prod, prod);
+
+       /* 4. If we are the owner, take control of the SMMU hardware */
+       if (owner) {
+               /* a. Wait for previous owner to finish */
+               atomic_cond_read_relaxed(&cmdq->owner_prod, VAL == llq.prod);
+
+               /* b. Stop gathering work by clearing the owned flag */
+               prod = atomic_fetch_andnot_relaxed(CMDQ_PROD_OWNED_FLAG,
+                                                  &cmdq->q.llq.atomic.prod);
+               prod &= ~CMDQ_PROD_OWNED_FLAG;
+               head.prod &= ~CMDQ_PROD_OWNED_FLAG;
+

Could it be a minor optimisation to advance the HW producer pointer at this
stage for the owner only? We know that its entries are written, and it
should be first in the new batch of commands (right?), so we could advance
the pointer to at least get the HW started.

I think that would be a valid thing to do, but it depends on the relative
cost of writing to prod compared to how long we're likely to wait. Given
that everybody has irqs disabled when writing out their commands, I wouldn't
expect the waiting to be a big issue,

For sure, but I'm thinking of the possible scenario where the the guy(s) we're waiting on have many more commands. Or they just joined the current gathering quite late, just prior to clearing the owner flag.

 although we could probably optimise
arm_smmu_cmdq_write_entries() into a memcpy() if we needed to.

In other words, I think we need numbers to justify that change.

Anyway, this is quite minor, and I will see if the change could be justified by numbers.

Cheers,
John


Thanks,

Will

.



_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to