Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp630164imm; Fri, 29 Jun 2018 03:54:55 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLbB9urWbstPLZ6mNMaYEupSPEKmuX4mVTUsXQd4d+/gthOvOJgK/gnIcWwEOBabXNPFjaf X-Received: by 2002:a17:902:7592:: with SMTP id j18-v6mr14031093pll.51.1530269695359; Fri, 29 Jun 2018 03:54:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530269695; cv=none; d=google.com; s=arc-20160816; b=iDAva6+tX0m8pPU17drYeBF5KZDPAAgDgP+i+F0ylH8fUn0kTZ8atQUruSWlgHRzB9 ENIsibXuUnRVjoW7AtceMbnvpUV6Z/KEhG8ciPG6k/sB9Jh8vxrdedZk7zb+IaaKJXQq u0MaEtfMlKxE/FvpWS+g2wb1yvJVsdTTL8zYG20NZSC7Ttd0MBpimpfKVg4Hbe8gSmVx UWvwlbx59MGr14/fmtZwoW67S61AZgKZhbc1dlwwV+na5886OHMGHtjynKm/o/9/lrfZ V0tgt231/ozAJDbdcPkp9wCAs0Ue/oAPO/hNZs/83Ky14XgouQvwMpO+Xt9ezy6McPN0 jHng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:date:cc:to:from:subject:message-id :arc-authentication-results; bh=XN+8qh5wHCglrnYKgL3viN5TSgO0D3i/9vyMZVseiJk=; b=bohLo7ba1vfxyjmX33UXYTPdRLZRsyVsfnVq092Cokj+ky9+zVQghruvtKAmfLviWr J2f6FQ/cuVj38K/oHSgVHzd9al65dumnz9/UUIP0ae4FZGMSnx4KgsGfpLeXoK/nB9Yd DM4wEAWIIi/H4xV2mc5yi9kZil7UcJ50zaMfN7Ogz8lOynIyJMPgYZiRBmZ4cgIko3/k sx/nEzRpuZms2Q5mOGsrlO+UBYXG1Fj+hVigtTEYzU24ZgEnsH64vZUUduBKSL5uDDsI he7HK/Ove+4noz28v5i1GTmGezYlX2l9Ogq8DwdOYGMGsdaNfnM/RKd2cJ89ZcFiDG4L U7VA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k14-v6si6592817pfd.23.2018.06.29.03.54.40; Fri, 29 Jun 2018 03:54:55 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753172AbeF2HIN (ORCPT + 99 others); Fri, 29 Jun 2018 03:08:13 -0400 Received: from mailgw01.mediatek.com ([210.61.82.183]:9775 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1752917AbeF2HIL (ORCPT ); Fri, 29 Jun 2018 03:08:11 -0400 X-UUID: 9cc52a9ffa6d40d6b794de87e4ba7559-20180629 Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by mailgw01.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 127705794; Fri, 29 Jun 2018 15:08:07 +0800 Received: from mtkcas09.mediatek.inc (172.21.101.178) by mtkmbs03n2.mediatek.inc (172.21.101.182) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Fri, 29 Jun 2018 15:08:05 +0800 Received: from [172.21.77.4] (172.21.77.4) by mtkcas09.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1210.3 via Frontend Transport; Fri, 29 Jun 2018 15:08:05 +0800 Message-ID: <1530256083.8518.36.camel@mtksdaap41> Subject: Re: [PATCH v22 2/4] mailbox: mediatek: Add Mediatek CMDQ driver From: CK Hu To: Houlong Wei CC: Jassi Brar , Matthias Brugger , Rob Herring , Daniel Kurtz , Sascha Hauer , , , , , , Sascha Hauer , "Philipp Zabel" , Nicolas Boichat , Bibby Hsieh , YT Shen , Daoyuan Huang , Jiaguang Zhang , Dennis-YC Hsieh , Monica Wang , "HS Liao" , , Date: Fri, 29 Jun 2018 15:08:03 +0800 In-Reply-To: <1530098172-31385-3-git-send-email-houlong.wei@mediatek.com> References: <1530098172-31385-1-git-send-email-houlong.wei@mediatek.com> <1530098172-31385-3-git-send-email-houlong.wei@mediatek.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.10.4-0ubuntu2 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-MTK: N Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, Houlong: Some inline comment. On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > CMDQ is used to help write registers with critical time limitation, > such as updating display configuration during the vblank. It controls > Global Command Engine (GCE) hardware to achieve this requirement. > Currently, CMDQ only supports display related hardwares, but we expect > it can be extended to other hardwares for future requirements. > > Signed-off-by: Houlong Wei > Signed-off-by: HS Liao > Signed-off-by: CK Hu > --- > drivers/mailbox/Kconfig | 10 + > drivers/mailbox/Makefile | 2 + > drivers/mailbox/mtk-cmdq-mailbox.c | 634 ++++++++++++++++++++++++++++++ > include/linux/mailbox/mtk-cmdq-mailbox.h | 70 ++++ > 4 files changed, 716 insertions(+) > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > [...] > + > +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread) > +{ > + u32 warm_reset; > + > + writel(CMDQ_THR_DO_WARM_RESET, thread->base + CMDQ_THR_WARM_RESET); > + if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET, > + warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET), > + 0, 10)) { > + dev_err(cmdq->mbox.dev, "reset GCE thread 0x%x failed\n", > + (u32)(thread->base - cmdq->base)); > + return -EFAULT; > + } > + writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES); The CMDQ_THR_SLOT_CYCLES looks like not relevant to reset. Maybe you just need to set this value when startup. > + > + return 0; > +} > + [...] > + > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct cmdq_thread *thread) > +{ > + struct cmdq *cmdq; > + struct cmdq_task *task; > + unsigned long curr_pa, end_pa; > + > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > + > + /* Client should not flush new tasks if suspended. */ > + WARN_ON(cmdq->suspended); > + > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > + task->cmdq = cmdq; > + INIT_LIST_HEAD(&task->list_entry); > + task->pa_base = pkt->pa_base; > + task->thread = thread; > + task->pkt = pkt; > + > + if (list_empty(&thread->task_busy_list)) { > + WARN_ON(clk_enable(cmdq->clock) < 0); > + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); > + > + writel(task->pa_base, thread->base + CMDQ_THR_CURR_ADDR); > + writel(task->pa_base + pkt->cmd_buf_size, > + thread->base + CMDQ_THR_END_ADDR); > + writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); > + writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); > + writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); > + > + if (thread->timeout_ms != CMDQ_NO_TIMEOUT) > + mod_timer(&thread->timeout, > + jiffies + msecs_to_jiffies(thread->timeout_ms)); I think the timeout processing should be done by client driver. The total time to execute a command buffer does not depend on GCE HW speed because the WFE (wait for event) command would wait for client HW event, so the total time depend on how long a client HW send this event to GCE and the timeout processing should be client driver's job. Each client may have different timeout processing mechanism, for example, if display could dynamic change panel frame rate between 120Hz and 60Hz, and the timeout time is 2 frame, so it may dynamically change timeout time between 17ms and 33ms. Another reason is that display have interrupt every vblank, and it could check timeout in that interrupt, so the timer in cmdq driver looks redundant. Because each client would define its own timeout processing mechanism, so it's not wise to put timeout processing in cmdq driver. > + } else { > + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > + curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR); > + end_pa = readl(thread->base + CMDQ_THR_END_ADDR); > + > + /* > + * Atomic execution should remove the following wfe, i.e. only > + * wait event at first task, and prevent to pause when running. > + */ > + if (thread->atomic_exec) { > + /* GCE is executing if command is not WFE */ > + if (!cmdq_thread_is_in_wfe(thread)) { > + cmdq_thread_resume(thread); > + cmdq_thread_wait_end(thread, end_pa); > + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > + /* set to this task directly */ > + writel(task->pa_base, > + thread->base + CMDQ_THR_CURR_ADDR); > + } else { > + cmdq_task_insert_into_thread(task); > + cmdq_task_remove_wfe(task); > + smp_mb(); /* modify jump before enable thread */ > + } > + } else { > + /* check boundary */ > + if (curr_pa == end_pa - CMDQ_INST_SIZE || > + curr_pa == end_pa) { > + /* set to this task directly */ > + writel(task->pa_base, > + thread->base + CMDQ_THR_CURR_ADDR); > + } else { > + cmdq_task_insert_into_thread(task); > + smp_mb(); /* modify jump before enable thread */ > + } > + } > + writel(task->pa_base + pkt->cmd_buf_size, > + thread->base + CMDQ_THR_END_ADDR); > + cmdq_thread_resume(thread); > + } > + list_move_tail(&task->list_entry, &thread->task_busy_list); > +} > + > +static void cmdq_task_exec_done(struct cmdq_task *task, bool err) > +{ > + struct device *dev = task->cmdq->mbox.dev; > + struct cmdq_cb_data cmdq_cb_data; > + > + dma_unmap_single(dev, task->pa_base, task->pkt->cmd_buf_size, > + DMA_TO_DEVICE); Move this to client driver. > + if (task->pkt->cb.cb) { > + cmdq_cb_data.err = err; > + cmdq_cb_data.data = task->pkt->cb.data; > + task->pkt->cb.cb(cmdq_cb_data); > + } > + list_del(&task->list_entry); > +} > + [...] > + > +static bool cmdq_mbox_last_tx_done(struct mbox_chan *chan) > +{ > + return true; > +} > + > +static const struct mbox_chan_ops cmdq_mbox_chan_ops = { > + .send_data = cmdq_mbox_send_data, > + .startup = cmdq_mbox_startup, > + .shutdown = cmdq_mbox_shutdown, > + .last_tx_done = cmdq_mbox_last_tx_done, Because mbox->txdone_poll is false, so you need not to implement last_tx_done. Regards, CK > +}; > + > +static struct mbox_chan *cmdq_xlate(struct mbox_controller *mbox, > + const struct of_phandle_args *sp) > +{ > + int ind = sp->args[0]; > + struct cmdq_thread *thread; > + > + if (ind >= mbox->num_chans) > + return ERR_PTR(-EINVAL); > + > + thread = mbox->chans[ind].con_priv; > + thread->timeout_ms = sp->args[1]; > + thread->priority = sp->args[2]; > + thread->atomic_exec = (sp->args[3] != 0); > + thread->chan = &mbox->chans[ind]; > + > + return &mbox->chans[ind]; > +} > + [...]