From patchwork Mon Mar 23 14:49:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 11453325 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 39CB5174A for ; Mon, 23 Mar 2020 14:52:21 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1819E20753 for ; Mon, 23 Mar 2020 14:52:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=ffwll.ch header.i=@ffwll.ch header.b="WmfhBL5y" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1819E20753 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ffwll.ch Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2754C6E271; Mon, 23 Mar 2020 14:51:20 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by gabe.freedesktop.org (Postfix) with ESMTPS id A58436E24E for ; Mon, 23 Mar 2020 14:51:01 +0000 (UTC) Received: by mail-wr1-x442.google.com with SMTP id 31so11420331wrs.3 for ; Mon, 23 Mar 2020 07:51:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ajR5dLK7zd/3v+8WpXJOKAdFiX9ApzmWPRFvMp354LA=; b=WmfhBL5ys3NyyQuAdm11b/euZ39Gs0CnPc5/SxrCpFLw3p1wFVzYoMdO5O096lYEP3 ne7ChOrbi2de+rmneIyi4gQh67Sza75lnOx+kXuP3boMyaDTcwfaJ5VkRm5k8zdwYw5u HziiGGegbFXPOwmZeOU2NWhSJdn2VPB/hAXPk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ajR5dLK7zd/3v+8WpXJOKAdFiX9ApzmWPRFvMp354LA=; b=Q/lzNqSb8fCUEZm3KZMxHX/H05fu3Vl8vT6F0GAvbnlJUY2GGaTzFY2lsfvb7VneTn O6GX2eVRzWnv/bqcH7F7hH1+09o46m5Kxa48CCEoXmw1tD4SLtvB/uw6XJUPsePipeh/ 7KlSKWXRgc+OpA77i8vFd0bNVTCzYkQ46phEM89C300jQhpqBPhUh9AeBbvbxaF1s6RG eEOuESGFpecKZLqO9wnwDk+iHJ1gaa40Nq3IGWbwxxrk809C/JBmE/7zG+gNeMcH70/k 6cCQBMv3wwpND36GgDGiNCNnaxR2uHXGIk/Ix5GMCgAxyX7HGEqyRlNV2KgkGC3KKQM6 7vYQ== X-Gm-Message-State: ANhLgQ1XmbqH2pl+UsfFSeKM5DgnVFG0IEDK+yHGhUpPz7EHrTGbkmAi Pcc7ixuYLNN70Y49gw2+f3PXv+FgIyXdCQ== X-Google-Smtp-Source: ADFU+vte+tHSyajzX9vNfo8THTb6CmeLw/x3L8SzuamX0cOO8NMrLEsza9y75FajLGH4xvoUu6cbaQ== X-Received: by 2002:a5d:540c:: with SMTP id g12mr25693149wrv.178.1584975059739; Mon, 23 Mar 2020 07:50:59 -0700 (PDT) Received: from phenom.ffwll.local ([2a02:168:57f4:0:efd0:b9e5:5ae6:c2fa]) by smtp.gmail.com with ESMTPSA id s22sm20376522wmc.16.2020.03.23.07.50.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 07:50:59 -0700 (PDT) From: Daniel Vetter To: DRI Development Subject: [PATCH 45/51] drm/gm12u320: Simplify upload work Date: Mon, 23 Mar 2020 15:49:44 +0100 Message-Id: <20200323144950.3018436-46-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323144950.3018436-1-daniel.vetter@ffwll.ch> References: <20200323144950.3018436-1-daniel.vetter@ffwll.ch> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Daniel Vetter , Daniel Vetter , Intel Graphics Development , Hans de Goede Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Instead of having a work item that never stops (which really should be a kthread), with a dedicated workqueue to not upset anyone else, use a delayed work. A bunch of changes: - We can throw out all the custom wakeup and requeue logic and state tracking. If we schedule the work with a 0 delay it'll get scheduled immediately. - Persistent state (frame & draw_status_timeout) need to be moved out of the work. - diff is bigger than the changes, biggest chunk is reindenting the work fn because it lost its while loop. Lots of code deleting as consequence all over. Specifically we can delete the drm_driver.release code now! v2: Review from Hans: - Use mod_delayed_work in the plane update path to make sure we do actually schedule immediately). In the worker we still want queue_delayed_work, which won't modify the timeout when the work is already scheduled. Which is exactly what we want if the work races with a plane update. - Switch to system_long_wq, Hans says on usb2 a plane upload can take 80 ms. Reviewed-by: Hans de Goede Signed-off-by: Daniel Vetter Cc: Hans de Goede Cc: "Noralf Trønnes" --- drivers/gpu/drm/tiny/gm12u320.c | 171 +++++++++++++------------------- 1 file changed, 68 insertions(+), 103 deletions(-) diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index 9627cbc3ec64..6f0ea2827d62 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -89,13 +89,12 @@ struct gm12u320_device { unsigned char *cmd_buf; unsigned char *data_buf[GM12U320_BLOCK_COUNT]; struct { - bool run; - struct workqueue_struct *workq; - struct work_struct work; - wait_queue_head_t waitq; + struct delayed_work work; struct mutex lock; struct drm_framebuffer *fb; struct drm_rect rect; + int frame; + int draw_status_timeout; } fb_update; }; @@ -183,19 +182,9 @@ static int gm12u320_usb_alloc(struct gm12u320_device *gm12u320) data_block_footer, DATA_BLOCK_FOOTER_SIZE); } - gm12u320->fb_update.workq = create_singlethread_workqueue(DRIVER_NAME); - if (!gm12u320->fb_update.workq) - return -ENOMEM; - return 0; } -static void gm12u320_usb_free(struct gm12u320_device *gm12u320) -{ - if (gm12u320->fb_update.workq) - destroy_workqueue(gm12u320->fb_update.workq); -} - static int gm12u320_misc_request(struct gm12u320_device *gm12u320, u8 req_a, u8 req_b, u8 arg_a, u8 arg_b, u8 arg_c, u8 arg_d) @@ -338,80 +327,77 @@ static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320) static void gm12u320_fb_update_work(struct work_struct *work) { struct gm12u320_device *gm12u320 = - container_of(work, struct gm12u320_device, fb_update.work); - int draw_status_timeout = FIRST_FRAME_TIMEOUT; + container_of(to_delayed_work(work), struct gm12u320_device, + fb_update.work); int block, block_size, len; - int frame = 0; int ret = 0; - while (gm12u320->fb_update.run) { - gm12u320_copy_fb_to_blocks(gm12u320); - - for (block = 0; block < GM12U320_BLOCK_COUNT; block++) { - if (block == GM12U320_BLOCK_COUNT - 1) - block_size = DATA_LAST_BLOCK_SIZE; - else - block_size = DATA_BLOCK_SIZE; - - /* Send data command to device */ - memcpy(gm12u320->cmd_buf, cmd_data, CMD_SIZE); - gm12u320->cmd_buf[8] = block_size & 0xff; - gm12u320->cmd_buf[9] = block_size >> 8; - gm12u320->cmd_buf[20] = 0xfc - block * 4; - gm12u320->cmd_buf[21] = block | (frame << 7); - - ret = usb_bulk_msg(gm12u320->udev, - usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT), - gm12u320->cmd_buf, CMD_SIZE, &len, - CMD_TIMEOUT); - if (ret || len != CMD_SIZE) - goto err; - - /* Send data block to device */ - ret = usb_bulk_msg(gm12u320->udev, - usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT), - gm12u320->data_buf[block], block_size, - &len, DATA_TIMEOUT); - if (ret || len != block_size) - goto err; - - /* Read status */ - ret = usb_bulk_msg(gm12u320->udev, - usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT), - gm12u320->cmd_buf, READ_STATUS_SIZE, &len, - CMD_TIMEOUT); - if (ret || len != READ_STATUS_SIZE) - goto err; - } + gm12u320_copy_fb_to_blocks(gm12u320); + + for (block = 0; block < GM12U320_BLOCK_COUNT; block++) { + if (block == GM12U320_BLOCK_COUNT - 1) + block_size = DATA_LAST_BLOCK_SIZE; + else + block_size = DATA_BLOCK_SIZE; + + /* Send data command to device */ + memcpy(gm12u320->cmd_buf, cmd_data, CMD_SIZE); + gm12u320->cmd_buf[8] = block_size & 0xff; + gm12u320->cmd_buf[9] = block_size >> 8; + gm12u320->cmd_buf[20] = 0xfc - block * 4; + gm12u320->cmd_buf[21] = + block | (gm12u320->fb_update.frame << 7); - /* Send draw command to device */ - memcpy(gm12u320->cmd_buf, cmd_draw, CMD_SIZE); ret = usb_bulk_msg(gm12u320->udev, usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT), - gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT); + gm12u320->cmd_buf, CMD_SIZE, &len, + CMD_TIMEOUT); if (ret || len != CMD_SIZE) goto err; + /* Send data block to device */ + ret = usb_bulk_msg(gm12u320->udev, + usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT), + gm12u320->data_buf[block], block_size, + &len, DATA_TIMEOUT); + if (ret || len != block_size) + goto err; + /* Read status */ ret = usb_bulk_msg(gm12u320->udev, usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT), gm12u320->cmd_buf, READ_STATUS_SIZE, &len, - draw_status_timeout); + CMD_TIMEOUT); if (ret || len != READ_STATUS_SIZE) goto err; - - draw_status_timeout = CMD_TIMEOUT; - frame = !frame; - - /* - * We must draw a frame every 2s otherwise the projector - * switches back to showing its logo. - */ - wait_event_timeout(gm12u320->fb_update.waitq, - !gm12u320->fb_update.run || - gm12u320->fb_update.fb != NULL, - IDLE_TIMEOUT); } + + /* Send draw command to device */ + memcpy(gm12u320->cmd_buf, cmd_draw, CMD_SIZE); + ret = usb_bulk_msg(gm12u320->udev, + usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT), + gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT); + if (ret || len != CMD_SIZE) + goto err; + + /* Read status */ + ret = usb_bulk_msg(gm12u320->udev, + usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT), + gm12u320->cmd_buf, READ_STATUS_SIZE, &len, + gm12u320->fb_update.draw_status_timeout); + if (ret || len != READ_STATUS_SIZE) + goto err; + + gm12u320->fb_update.draw_status_timeout = CMD_TIMEOUT; + gm12u320->fb_update.frame = !gm12u320->fb_update.frame; + + /* + * We must draw a frame every 2s otherwise the projector + * switches back to showing its logo. + */ + queue_delayed_work(system_long_wq, &gm12u320->fb_update.work, + IDLE_TIMEOUT); + return; err: /* Do not log errors caused by module unload or device unplug */ @@ -446,36 +432,24 @@ static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb, mutex_unlock(&gm12u320->fb_update.lock); if (wakeup) - wake_up(&gm12u320->fb_update.waitq); + mod_delayed_work(system_long_wq, &gm12u320->fb_update.work, 0); if (old_fb) drm_framebuffer_put(old_fb); } -static void gm12u320_start_fb_update(struct gm12u320_device *gm12u320) -{ - mutex_lock(&gm12u320->fb_update.lock); - gm12u320->fb_update.run = true; - mutex_unlock(&gm12u320->fb_update.lock); - - queue_work(gm12u320->fb_update.workq, &gm12u320->fb_update.work); -} - static void gm12u320_stop_fb_update(struct gm12u320_device *gm12u320) { - mutex_lock(&gm12u320->fb_update.lock); - gm12u320->fb_update.run = false; - mutex_unlock(&gm12u320->fb_update.lock); + struct drm_framebuffer *old_fb; - wake_up(&gm12u320->fb_update.waitq); - cancel_work_sync(&gm12u320->fb_update.work); + cancel_delayed_work_sync(&gm12u320->fb_update.work); mutex_lock(&gm12u320->fb_update.lock); - if (gm12u320->fb_update.fb) { - drm_framebuffer_put(gm12u320->fb_update.fb); - gm12u320->fb_update.fb = NULL; - } + old_fb = gm12u320->fb_update.fb; + gm12u320->fb_update.fb = NULL; mutex_unlock(&gm12u320->fb_update.lock); + + drm_framebuffer_put(old_fb); } static int gm12u320_set_ecomode(struct gm12u320_device *gm12u320) @@ -583,11 +557,11 @@ static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private; struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT }; + struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private; + gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT; gm12u320_fb_mark_dirty(plane_state->fb, &rect); - gm12u320_start_fb_update(gm12u320); } static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe) @@ -622,13 +596,6 @@ static const uint64_t gm12u320_pipe_modifiers[] = { DRM_FORMAT_MOD_INVALID }; -static void gm12u320_driver_release(struct drm_device *dev) -{ - struct gm12u320_device *gm12u320 = dev->dev_private; - - gm12u320_usb_free(gm12u320); -} - DEFINE_DRM_GEM_FOPS(gm12u320_fops); static struct drm_driver gm12u320_drm_driver = { @@ -640,7 +607,6 @@ static struct drm_driver gm12u320_drm_driver = { .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, - .release = gm12u320_driver_release, .fops = &gm12u320_fops, DRM_GEM_SHMEM_DRIVER_OPS, }; @@ -670,9 +636,8 @@ static int gm12u320_usb_probe(struct usb_interface *interface, return -ENOMEM; gm12u320->udev = interface_to_usbdev(interface); - INIT_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work); + INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work); mutex_init(&gm12u320->fb_update.lock); - init_waitqueue_head(&gm12u320->fb_update.waitq); dev = &gm12u320->dev; ret = devm_drm_dev_init(&interface->dev, dev, &gm12u320_drm_driver);