Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp4782995pxu; Tue, 22 Dec 2020 00:11:03 -0800 (PST) X-Google-Smtp-Source: ABdhPJwrb43VegGN+dQwPD0g/m6jr4AIKBKr+Cw4CPgxGKwBfHr79aLF+1hdJBejBef54LXhEBM/ X-Received: by 2002:a50:fc0d:: with SMTP id i13mr13386700edr.171.1608624663275; Tue, 22 Dec 2020 00:11:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1608624663; cv=none; d=google.com; s=arc-20160816; b=QwfH3t623rmtKUNQGq6U7t6fq0hJikJXoEuQpyaUs//U8tSXDkJ13/jsMGC4f1I76K da9HRdXPmGxAkchOos782d/gS6Oc4UwhC2smfMxFz+XoqcqdW47AApogEIdEIVBP1DKC n+PnDTvVMp5XODPTOpnQBycMYfnH5vAHszc41TtnXWvprdi3a2iTYNCigYOe13V38+/H z2PNfVdA7dyNF6vipIv9raizjNxQOaKaq5sWNWMas6OmrAe/uknWTH9ohCG03r5uhzP0 wkdH80o1EEyhIdPGoR9bYsPHShWlj5jgOp25NtqY4xtenkVSrUe2STrNWfCGj0vOx4JU Ya4w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=BiYWxq8zQJdTzAa9ciawdWs0btCvpZMcPV4VM/Cx3uM=; b=TW7c3HhvRrplXPTpq0S8t+n3Z+43LcbKaI7lB7Tx5uKX+BcdQg5cB9G71EM4IG/t9H fD8sw+Lvgmk27AuG/5ywDDv1y1LWOJAeKwh2TNtxmbWQo+FAJuGLRRbYlrIGrE9xVBlN /ab3EwDmgKktzr6h0rS0wlJ6R6CtMDtWJu9uk1MUpUGAtj4rf5X3fVunKXo1P8c0fZwR rv4skuiAtsMvGo42IrMG/I9bGDBgZ/aTEzpA6tZcsLoLvqPQ/S1m7Qc/FtPv/Way+dNX mQu0VjFoEQGF9+axmBUIHopVHkNyup7c4jxBOna6VvjBLdPK5NG2H3cMXc/yUSbtKSak 9KqA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=j4kMffjS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id bo6si11442674edb.434.2020.12.22.00.10.40; Tue, 22 Dec 2020 00:11:03 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=j4kMffjS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726081AbgLVIIo (ORCPT + 99 others); Tue, 22 Dec 2020 03:08:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37620 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725962AbgLVIIo (ORCPT ); Tue, 22 Dec 2020 03:08:44 -0500 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 19A7DC0613D6; Tue, 22 Dec 2020 00:08:04 -0800 (PST) Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 898E89E6; Tue, 22 Dec 2020 09:08:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1608624482; bh=tEFcEohsPVRb33DDASy/wcqKa3yFs9oS5ip/v2qdvbg=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=j4kMffjSwMclhoHzTN2gfCEx1rmVijJLXUNsdvD4Bt6rJv7lyOfoxNCKF3LwloWGo bKZ7dgDsYJec7a5dLBuzhWgCl+E/nTJCzYKweuj8e7M5sMCSPs+66EYwZYU5lpCZlZ L0RkXkvnLPsIi+hrI0zR4N9mv/HaDNHQWJh8tIrs= Date: Tue, 22 Dec 2020 10:07:55 +0200 From: Laurent Pinchart To: Ricardo Ribalda Cc: Mauro Carvalho Chehab , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v5 02/12] media: uvcvideo: Allow more that one asyc_ctrl Message-ID: References: <20201221164819.792019-1-ribalda@chromium.org> <20201221164819.792019-3-ribalda@chromium.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20201221164819.792019-3-ribalda@chromium.org> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Ricardo, Thank you for the patch. On Mon, Dec 21, 2020 at 05:48:09PM +0100, Ricardo Ribalda wrote: > The current implementation allocates memory for only one async_control. > If we get a second event before we have processed the previous one, the > old one gets lost. > > Introduce a dynamic memory allocation and a list to handle the > async_controls. Thinking some more about this, do we need to go through the work queue at all for GPIO-based events ? Could the part of uvc_ctrl_status_event_work() before the URB resubmission be moved to another function, which would be called directly by the GPIO threaded IRQ handler ? > Signed-off-by: Ricardo Ribalda > --- > drivers/media/usb/uvc/uvc_ctrl.c | 49 ++++++++++++++++++++++++++------ > drivers/media/usb/uvc/uvcvideo.h | 19 ++++++++----- > 2 files changed, 52 insertions(+), 16 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > index aa18dcdf8165..69b2fc6ce12c 100644 > --- a/drivers/media/usb/uvc/uvc_ctrl.c > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > @@ -1275,11 +1275,9 @@ static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain, > uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes); > } > > -static void uvc_ctrl_status_event_work(struct work_struct *work) > +static void __uvc_ctrl_status_event_work(struct uvc_device *dev, > + struct uvc_ctrl_work *w) > { > - struct uvc_device *dev = container_of(work, struct uvc_device, > - async_ctrl.work); > - struct uvc_ctrl_work *w = &dev->async_ctrl; > struct uvc_video_chain *chain = w->chain; > struct uvc_control_mapping *mapping; > struct uvc_control *ctrl = w->ctrl; > @@ -1321,23 +1319,54 @@ static void uvc_ctrl_status_event_work(struct work_struct *work) > ret); > } > > +static void uvc_ctrl_status_event_work(struct work_struct *work) > +{ > + struct uvc_device *dev = container_of(work, struct uvc_device, > + async_ctrl_work); > + struct uvc_ctrl_work *w; > + > + do { > + mutex_lock(&dev->async_ctrl_lock); > + w = list_first_entry_or_null(&dev->async_ctrl_list, > + struct uvc_ctrl_work, > + list); > + if (w) > + list_del(&w->list); > + mutex_unlock(&dev->async_ctrl_lock); > + > + if (!w) > + return; > + > + __uvc_ctrl_status_event_work(dev, w); > + kfree(w); > + } while (w); > +} > + > bool uvc_ctrl_status_event(struct urb *urb, struct uvc_video_chain *chain, > struct uvc_control *ctrl, const u8 *data) > { > struct uvc_device *dev = chain->dev; > - struct uvc_ctrl_work *w = &dev->async_ctrl; > + struct uvc_ctrl_work *w; > > if (list_empty(&ctrl->info.mappings)) { > ctrl->handle = NULL; > return false; > } > > + w = kzalloc(sizeof(*w), GFP_KERNEL); > + if (WARN(!w, "Not enough memory to trigger uvc event")) > + return false; > + > memcpy(w->data, data, ctrl->info.size); > w->urb = urb; > w->chain = chain; > w->ctrl = ctrl; > > - schedule_work(&w->work); > + mutex_lock(&dev->async_ctrl_lock); > + list_add_tail(&w->list, &dev->async_ctrl_list); > + mutex_unlock(&dev->async_ctrl_lock); > + > + schedule_work(&dev->async_ctrl_work); > > return true; > } > @@ -2277,7 +2306,9 @@ int uvc_ctrl_init_device(struct uvc_device *dev) > struct uvc_entity *entity; > unsigned int i; > > - INIT_WORK(&dev->async_ctrl.work, uvc_ctrl_status_event_work); > + INIT_WORK(&dev->async_ctrl_work, uvc_ctrl_status_event_work); > + mutex_init(&dev->async_ctrl_lock); > + INIT_LIST_HEAD(&dev->async_ctrl_list); > > /* Walk the entities list and instantiate controls */ > list_for_each_entry(entity, &dev->entities, list) { > @@ -2348,8 +2379,8 @@ void uvc_ctrl_cleanup_device(struct uvc_device *dev) > unsigned int i; > > /* Can be uninitialized if we are aborting on probe error. */ > - if (dev->async_ctrl.work.func) > - cancel_work_sync(&dev->async_ctrl.work); > + if (dev->async_ctrl_work.func) > + cancel_work_sync(&dev->async_ctrl_work); > > /* Free controls and control mappings for all entities. */ > list_for_each_entry(entity, &dev->entities, list) { > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h > index 0db6c2e0bd98..afcaf49fad1a 100644 > --- a/drivers/media/usb/uvc/uvcvideo.h > +++ b/drivers/media/usb/uvc/uvcvideo.h > @@ -637,6 +637,14 @@ struct uvc_device_info { > u32 meta_format; > }; > > +struct uvc_ctrl_work { > + struct list_head list; > + struct urb *urb; > + struct uvc_video_chain *chain; > + struct uvc_control *ctrl; > + u8 data[UVC_MAX_STATUS_SIZE]; > +}; > + > struct uvc_device { > struct usb_device *udev; > struct usb_interface *intf; > @@ -673,13 +681,10 @@ struct uvc_device { > struct input_dev *input; > char input_phys[64]; > > - struct uvc_ctrl_work { > - struct work_struct work; > - struct urb *urb; > - struct uvc_video_chain *chain; > - struct uvc_control *ctrl; > - u8 data[UVC_MAX_STATUS_SIZE]; > - } async_ctrl; > + /* Async control */ > + struct work_struct async_ctrl_work; > + struct list_head async_ctrl_list; > + struct mutex async_ctrl_lock; > }; > > enum uvc_handle_state { -- Regards, Laurent Pinchart