Re: usb: dwc3: dwc3 errors while video streaming with uvc-gadget

2018-11-05 Thread Laurent Pinchart
Hi Felipe,

On Monday, 5 November 2018 14:05:59 EET Felipe Balbi wrote:
> Laurent Pinchart writes:
> > On Saturday, 3 November 2018 23:07:33 EET Terence Neill wrote:
> >> Hi folks,
> >> 
> >> Thanks for the replies, I really appreciate them.  I've made some
> >> progress on this.  I'm new to USB so apologies if the following text is
> >> incorrect or is just bizarre!:
> >> 
> >> 1. The problem with streaming_maxpacket set to 2048 seemed to be caused
> >> by not enough requests being queued with the dwc3 driver at one time,
> >> resulting in request starvation at higher bandwidths.  Increasing the
> >> value of the UVC_NUM_REQUESTS macro from 4 to 16 (in
> >> drivers/usb/gadget/function/uvc.h) seemed to fix this problem.
> > 
> > This clearly needs to be fixed. I wonder if we should try to compute a
> > good value at runtime, or go for a large enough fixed value for all cases.
> 
> just go for something large. Computing in runtime would involving
> measuring latency in runtime and adapting your queue accordingly. Too
> much work for very little benefit.

I've received a request some time ago from a UVC gadget user who wanted to 
bump the UVC_NUM_REQUESTS up to store a full video frame. That's likely too 
much, we'll have to decide on a proper middle ground.

> >> 2. It looks like the problem that was happening with max_packet set to
> >> 3072 was caused by the isochronous transfer being queued for a microframe
> >> number in the past (the assumption is that there is the code just wasn't
> >> getting the first microframe queued in time).  To get around this
> >> problem, I changed the DWC3_ALIGN_FRAME() macro to add an offset of one
> >> video frame (the video is running at 10fps so about 800 microframes).
> >> This fixed the startup problem at high bandwidth. At the moment, the
> >> objective of the investigation is to prove throughput, so some latency
> >> can be accommodated.
> > 
> > Felipe has worked on this recently, but if I recall correctly there were
> > still issues that prevented patches from being upstreamed.
> 
> true
> 
> >> From reading some more about USB, it looks like isochronous transfers may
> >> have the option sending zero length packets whenever there is no data to
> >> send?  Is this true?  If so, would this be a possible option to move
> >> forward with this issue - eliminating the need to handle missed isocs at
> >> the f_uvc layer?
> > 
> > We will always have to handle the missed intervals, as something could go
> > wrong and result in such a situation, and we don't want to freeze the
> > stream in that case. Transmitting 0-length packets could be an option,
> > but I wonder how much CPU overhead it would generate (both on the gadget
> > and host side). Felipe, do you have any experience with this and/or
> > recommendation ?
> 
> I'd expect the UDC to handle that in HW. At least dwc3 does, don't know
> about MUSB and the others.

But dwc3 still returns missed intervals errors in that case, right ? I think 
Terence proposal was to explicitly queue ZLP requests in order to avoid 
missing any interval.

> >> I was reading the summary of the dwc3 driver features at
> >> https://github.com/torvalds/linux/blob/master/Documentation/driver-api/us
> >> b/d wc3.rst and point 7 mentions support for "Superspeed Bulk Streams"
> >> but I was unsure if this meant that ONLY bulk streams were supported or
> >> whether isochronous streams were also supported?
> > 
> > That's a question for Felipe :-)
> 
> Super speed defines streams for bulk endpoints only.

-- 
Regards,

Laurent Pinchart





Re: usb: dwc3: dwc3 errors while video streaming with uvc-gadget

2018-11-05 Thread Laurent Pinchart
f the dwc3 driver features at
> https://github.com/torvalds/linux/blob/master/Documentation/driver-api/usb/d
> wc3.rst and point 7 mentions support for "Superspeed Bulk Streams" but I
> was unsure if this meant that ONLY bulk streams were supported or whether
> isochronous streams were also supported?

That's a question for Felipe :-)

-- 
Regards,

Laurent Pinchart





Re: usb: dwc3: dwc3 errors while video streaming with uvc-gadget

2018-11-02 Thread Laurent Pinchart
Hello,

On Friday, 2 November 2018 11:50:47 EET Roger Quadros wrote:
> On 15/10/18 19:34, Terence Neill wrote:
> > Hi Felipe,
> > 
> > I am having some issues when attempting to stream 1280x720 uncompressed
> > video @ 10fps over a USB 2.0 High-Speed link.
> > 
> > The system setup is:
> > 
> > WebCam --- USB 2.0 link --->  x86 Linux Machine running uvc-gadget 
> > USB 2.0 link ---> x86 Host Machine running Windows 10.
> > 
> > When running this setup, I am experiencing the following:
> > 
> > 1. With streaming_maxpacket set to 2048 (2 transactions per microframe)
> > the video will stream for approximately one minute before terminating
> > with "VS request completed with status -18" reported in the kernel logs.
> > 
> > 2. With streaming_maxpacket set to 3072 (3 transactions per microframe)
> > the video does not stream at all with "VS request completed with status
> > -18" reported in the error logs.
> 
> There were some updates pushed recently to the uvc-gadget utility [1].
> Could you please try with that and see if this issue still persists? Thanks.
> 
> [1] http://git.ideasonboard.org/uvc-gadget.git

Worth a try, but I don't think this will make a difference. The UVC gadget 
function driver is known not to handle missed isoc intervals correctly. I 
started having a look at that, but unfortunately had to move to other 
projects, and I don't know when I'll have the time to get back to this issue 
:-/

> > From trying to analyse what is going on (looking at traces), it looks
> > like the dwc3 driver is initially forwarding video buffers as expected.
> > Because the bandwdith of the USB link is greater than the bandiwidth of
> > the video being transmitted, at some point the dwc3 driver looks for
> > more buffers to transmit and there aren't any.  At this point, it seems
> > to enter a state that is not recovered from whenever a new buffer
> > becomes available to transmit.
> > 
> > I have included a trace and register dump as requested for further
> > analysis.
> > 
> > In terms of hardware/software versions for the test setup:
> > 
> > Linux machine - Intel n4200 - running Ubuntu 18.04 - kernel version
> > 4.19.0-041900rc8-generic (I updated to this version this morning to make
> > sure I was using the latest dwc3 driver, the same problem exists (with a
> > different error code -104) with the stock Ubuntu 18.04 kernel).
> > 
> > Windows machine - Core i5-4570 - Windows 10 Enterprise.
> > 
> > Any help with further investigation of this problem would be appreciated? 
> > Could this problem be caused by the configuration setup that I'm using
> > for the uvc gadget?
> > 
> > Thanks in advance for your help,

-- 
Regards,

Laurent Pinchart





Re: UVC gadget changes for v4.20

2018-10-02 Thread Laurent Pinchart
Hi Felipe,

On Tuesday, 2 October 2018 10:26:25 EEST Felipe Balbi wrote:
> Laurent Pinchart  writes:
> > Hi Felipe,
> > 
> > (CC'ing Greg, in case you're on vacation)
> > 
> > Ping ? I'd really like to get this merged in v4.20. Do you think that
> > would be possible ?
> 
> applying patches today. Are you merging this elsewhere or can I take it
> as patches?

Thank you ! You can take them as patches if needed, I sent a pull request for 
your convenience as I assumed a git merge would be easier, but that's up to 
you.

-- 
Regards,

Laurent Pinchart





Re: UVC gadget changes for v4.20

2018-10-01 Thread Laurent Pinchart
Hi Felipe,

(CC'ing Greg, in case you're on vacation)

Ping ? I'd really like to get this merged in v4.20. Do you think that would be 
possible ?

On Tuesday, 25 September 2018 19:58:50 EEST Laurent Pinchart wrote:
> Hi Felipe,
> 
> The following changes since commit 5b394b2ddf0347bef56e50c69a58773c94343ff3:
> 
>   Linux 4.19-rc1 (2018-08-26 14:11:59 -0700)
> 
> are available in the Git repository at:
> 
>   git://linuxtv.org/pinchartl/media.git tags/uvcg-20180925
> 
> for you to fetch changes up to 3fb2fd76eda265ce5421318de38dd9b9f7c54737:
> 
>   usb: gadget: uvc: configfs: Use %u to print unsigned int values
> (2018-09-25 18:48:10 +0300)
> 
> 
> UVC gadget updates for v4.20
> 
> - configfs cleanups, fixes and extensions
> - Endianness fixes
> - Miscellaneous cleanups
> 
> 
> Joel Pepper (2):
>   usb: gadget: uvc: configfs: Add bFrameIndex attributes
>   usb: gadget: uvc: configfs: Prevent format changes after linking
> header
> 
> Laurent Pinchart (14):
>   usb: gadget: uvc: configfs: Don't wrap groups unnecessarily
>   usb: gadget: uvc: configfs: Add section header comments
>   usb: gadget: uvc: configfs: Drop leaked references to config items
>   usb: gadget: uvc: configfs: Allocate groups dynamically
>   usb: gadget: uvc: configfs: Add interface number attributes
>   usb: gadget: uvc: configfs: Add bFormatIndex attributes
>   usb: gadget: uvc: Factor out video USB request queueing
>   usb: gadget: uvc: Only halt video streaming endpoint in bulk mode
>   usb: gadget: uvc: Replace plain printk() with dev_*()
>   usb: gadget: uvc: Remove uvc_set_trace_param() function
>   usb: video: Fix endianness mismatches in descriptor structures
>   usb: gadget: uvc: configfs: Fix operation on big endian platforms
>   usb: gadget: uvc: configfs: Simplify attributes macros
>   usb: gadget: uvc: configfs: Use %u to print unsigned int values
> 
> Paul Elder (1):
>   usb: gadget: uvc: configfs: Sort frame intervals upon writing
> 
>  Documentation/ABI/testing/configfs-usb-gadget-uvc |   24 +
>  drivers/usb/gadget/function/f_uvc.c   |   57 +-
>  drivers/usb/gadget/function/u_uvc.h   |3 +
>  drivers/usb/gadget/function/uvc.h |   16 +-
>  drivers/usb/gadget/function/uvc_configfs.c| 1168 +
>  drivers/usb/gadget/function/uvc_v4l2.c|4 +-
>  drivers/usb/gadget/function/uvc_video.c   |   48 +-
>  drivers/usb/gadget/function/uvc_video.h   |2 +-
>  include/uapi/linux/usb/video.h|  304 +++---
>  9 files changed, 916 insertions(+), 710 deletions(-)

-- 
Regards,

Laurent Pinchart





UVC gadget changes for v4.20

2018-09-25 Thread Laurent Pinchart
Hi Felipe,

The following changes since commit 5b394b2ddf0347bef56e50c69a58773c94343ff3:

  Linux 4.19-rc1 (2018-08-26 14:11:59 -0700)

are available in the Git repository at:

  git://linuxtv.org/pinchartl/media.git tags/uvcg-20180925

for you to fetch changes up to 3fb2fd76eda265ce5421318de38dd9b9f7c54737:

  usb: gadget: uvc: configfs: Use %u to print unsigned int values (2018-09-25 
18:48:10 +0300)


UVC gadget updates for v4.20

- configfs cleanups, fixes and extensions
- Endianness fixes
- Miscellaneous cleanups


Joel Pepper (2):
  usb: gadget: uvc: configfs: Add bFrameIndex attributes
  usb: gadget: uvc: configfs: Prevent format changes after linking header

Laurent Pinchart (14):
  usb: gadget: uvc: configfs: Don't wrap groups unnecessarily
  usb: gadget: uvc: configfs: Add section header comments
  usb: gadget: uvc: configfs: Drop leaked references to config items
  usb: gadget: uvc: configfs: Allocate groups dynamically
  usb: gadget: uvc: configfs: Add interface number attributes
  usb: gadget: uvc: configfs: Add bFormatIndex attributes
  usb: gadget: uvc: Factor out video USB request queueing
  usb: gadget: uvc: Only halt video streaming endpoint in bulk mode
  usb: gadget: uvc: Replace plain printk() with dev_*()
  usb: gadget: uvc: Remove uvc_set_trace_param() function
  usb: video: Fix endianness mismatches in descriptor structures
  usb: gadget: uvc: configfs: Fix operation on big endian platforms
  usb: gadget: uvc: configfs: Simplify attributes macros
  usb: gadget: uvc: configfs: Use %u to print unsigned int values

Paul Elder (1):
  usb: gadget: uvc: configfs: Sort frame intervals upon writing

 Documentation/ABI/testing/configfs-usb-gadget-uvc |   24 +
 drivers/usb/gadget/function/f_uvc.c   |   57 +-
 drivers/usb/gadget/function/u_uvc.h   |3 +
 drivers/usb/gadget/function/uvc.h |   16 +-
 drivers/usb/gadget/function/uvc_configfs.c| 1168 ++-
 drivers/usb/gadget/function/uvc_v4l2.c|4 +-
 drivers/usb/gadget/function/uvc_video.c   |   48 +-
 drivers/usb/gadget/function/uvc_video.h   |2 +-
 include/uapi/linux/usb/video.h|  304 +++---
 9 files changed, 916 insertions(+), 710 deletions(-)

-- 
Regards,

Laurent Pinchart





Re: [PATCH v2 8/8] usb: gadget: uvc: configfs: Prevent format changes after linking header

2018-09-24 Thread Laurent Pinchart
Hi Kieran,

On Monday, 24 September 2018 15:50:45 EEST Kieran Bingham wrote:
> On 01/08/18 22:55, Laurent Pinchart wrote:
> > From: Joel Pepper 
> > 
> > While checks are in place to avoid attributes and children of a format
> > being manipulated after the format is linked into the streaming header,
> > the linked flag was never actually set, invalidating the protections.
> 
> That explains what's wrong, but not what we do about it. How about adding:
> 
> "Update the flag as appropriate in the header link calls."

Sounds good to me, I'll update that.

> > Signed-off-by: Joel Pepper 
> 
> Missing and S-o-B from Laurent here? (I guess that will be added later?)

I haven't modified the patch, so haven't added my SoB to send it to the 
mailing list. I'll add it before issuing the pull request.

> Otherwise,
> 
> Reviewed-by: Kieran Bingham 
> 
> > ---
> > 
> >  drivers/usb/gadget/function/uvc_configfs.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> > b/drivers/usb/gadget/function/uvc_configfs.c index
> > b8763343dcae..799dc32c5bc7 100644
> > --- a/drivers/usb/gadget/function/uvc_configfs.c
> > +++ b/drivers/usb/gadget/function/uvc_configfs.c
> > @@ -928,6 +928,7 @@ static int uvcg_streaming_header_allow_link(struct
> > config_item *src,> 
> > format_ptr->fmt = target_fmt;
> > list_add_tail(_ptr->entry, _hdr->formats);
> > ++src_hdr->num_fmt;
> > 
> > +   ++target_fmt->linked;
> > 
> >  out:
> > mutex_unlock(>lock);
> > 
> > @@ -965,6 +966,8 @@ static void uvcg_streaming_header_drop_link(struct
> > config_item *src,> 
> > break;
> > 
> > }
> > 
> > +   --target_fmt->linked;
> > +
> > 
> >  out:
> > mutex_unlock(>lock);
> > mutex_unlock(su_mutex);


-- 
Regards,

Laurent Pinchart





Re: [PATCH v2 7/8] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-09-24 Thread Laurent Pinchart
Hi Kieran,

On Monday, 24 September 2018 15:22:57 EEST Kieran Bingham wrote:
> On 01/08/18 22:55, Laurent Pinchart wrote:
> > From: Joel Pepper 
> > 
> > - Add bFrameIndex as a UVCG_FRAME_ATTR_RO for each frame size.
> > - Automatically assign ascending bFrameIndex to each frame in a format.
> > 
> > Before all "bFrameindex" attributes were set to "1" with no way to
> > configure the gadget otherwise. This resulted in the host always
> > negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
> > After the negotiation the host driver will set the user or application
> > selected framesize, while the gadget is actually set to the first
> > framesize.
> 
> s/framesize/frame size/ *3 above ? (or alternatively frame-size?)
> 
> > Now, when the containing format is linked into the streaming header,
> > iterate over all child frame descriptors and assign ascending indices.
> > The automatically assigned indices can be read from the new read only
> > bFrameIndex configsfs attribute in each frame descriptor item.
> 
> s/configsfs/configfs/
> 
> > Signed-off-by: Joel Pepper 
> > [Simplified documentation, renamed function, blank space update]
> > Signed-off-by: Laurent Pinchart 
> > ---
> > 
> >  Documentation/ABI/testing/configfs-usb-gadget-uvc |  8 
> >  drivers/usb/gadget/function/uvc_configfs.c| 56 ++
> >  2 files changed, 64 insertions(+)

[snip]

> > diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> > b/drivers/usb/gadget/function/uvc_configfs.c index
> > 5cee8aca3734..b8763343dcae 100644
> > --- a/drivers/usb/gadget/function/uvc_configfs.c
> > +++ b/drivers/usb/gadget/function/uvc_configfs.c
> > @@ -868,6 +868,8 @@ static struct uvcg_streaming_header
> > *to_uvcg_streaming_header(struct config_item> 
> > return container_of(item, struct uvcg_streaming_header, item);
> >  
> >  }
> > 
> > +static void uvcg_format_set_indices(struct config_group *fmt);
> > +
> 
> Do we need to forward declare here?
> 
> Couldn't we move the uvcg_format_set_indices() implementation up ?
> Or is it preferred to keep that code down in the lower section.

You know how much I dislike forward-declarations. I tried to fix this one, but 
uvcg_format_set_indices() can't be moved up as-is as it depends on the 
definition of the uvcg_frame structure. I attempted to reorganize the code in 
a more logical way but gave up given how large the resulting change was even 
before I got it to compile, and how the new organization was less logical :-(

> With a decision made on that, and the typo fixed in the commit message:
> 
> Reviewed-by: Kieran Bingham 

Thank you. I'll keep the forward declaration for now. I might give it a try 
again later.

> >  static int uvcg_streaming_header_allow_link(struct config_item *src,
> >  
> > struct config_item *target)
> >  
> >  {
> > 
> > @@ -915,6 +917,8 @@ static int uvcg_streaming_header_allow_link(struct
> > config_item *src,> 
> > if (!target_fmt)
> > 
> > goto out;
> > 
> > +   uvcg_format_set_indices(to_config_group(target));
> > +
> > 
> > format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
> > if (!format_ptr) {
> > 
> > ret = -ENOMEM;
> > 
> > @@ -1146,6 +1150,41 @@ end: 
> > \
> > 
> > \
> >  
> >  UVC_ATTR(uvcg_frame_, cname, aname);
> > 
> > +static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
> > +char *page)
> > +{
> > +   struct uvcg_frame *f = to_uvcg_frame(item);
> > +   struct uvcg_format *fmt;
> > +   struct f_uvc_opts *opts;
> > +   struct config_item *opts_item;
> > +   struct config_item *fmt_item;
> > +   struct mutex *su_mutex = >item.ci_group->cg_subsys->su_mutex;
> > +   int result;
> > +
> > +   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
> > +
> > +   fmt_item = f->item.ci_parent;
> > +   fmt = to_uvcg_format(fmt_item);
> > +
> > +   if (!fmt->linked) {
> > +   result = -EBUSY;
> > +   goto out;
> > +   }
> > +
> > +   opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
> > +   opts = to_f_uvc_opts(opts_item);
> > +
> > +   mutex_lock(>lock);
> > +   res

Re: [PATCH 0/3] Fix OMAP EHCI probe & assorted cleanups

2018-09-23 Thread Laurent Pinchart
Hi Lee,

On Sunday, 23 September 2018 18:38:28 EEST Lee Jones wrote:
> On Sun, 23 Sep 2018, Lee Jones wrote:
> > On Sun, 23 Sep 2018, Laurent Pinchart wrote:
> >> On Tuesday, 11 September 2018 19:25:38 EEST Tony Lindgren wrote:
> >>> * Laurent Pinchart [180911 16:12]:
> >>>> On Tuesday, 11 September 2018 18:16:41 EEST Tony Lindgren wrote:
> >>>>> * Laurent Pinchart [180911 15:10]:
> >>>>>> Hello,
> >>>>>> 
> >>>>>> This series fixes a v4.19-rc1 regression that results in OMAP EHCI
> >>>>>> failing to probe (patch 1/3) and then moves on to cleaning up
> >>>>>> related code (patches 2/3 and 3/3).
> >>>>>> 
> >>>>>> The first patch is a regression fix and should thus be merged
> >>>>>> before v4.19. The other two patches can wait until v4.20.
> >>>>> 
> >>>>> Hmm can you please check again with this patch applied:
> >>>>> 
> >>>>> "[PATCH] mfd: omap-usb-host: Fix dts probe of children"
> >>>> 
> >>>> This fixes the issue for me.
> >>> 
> >>>> Tested-by: Laurent Pinchart 
> >>> 
> >>> OK good to hear.
> >> 
> >> The fix is still not in v4.19-rc4 :-S Could you make sure it doesn't
> >> miss v4.19 ?
> > 
> > I'm going to send these today:
> >   mfd: omap-usb-host: Fix dts probe of children
> >   mfd: da9063: Fix DT probing with constraints
> 
> Greg just pulled.

Thank you, much appreciated.

-- 
Regards,

Laurent Pinchart





Re: [PATCH 0/3] Fix OMAP EHCI probe & assorted cleanups

2018-09-23 Thread Laurent Pinchart
Hi Tony,

On Tuesday, 11 September 2018 19:25:38 EEST Tony Lindgren wrote:
> * Laurent Pinchart  [180911 16:12]:
> > On Tuesday, 11 September 2018 18:16:41 EEST Tony Lindgren wrote:
> >> * Laurent Pinchart  [180911 15:10]:
> >>> Hello,
> >>> 
> >>> This series fixes a v4.19-rc1 regression that results in OMAP EHCI
> >>> failing to probe (patch 1/3) and then moves on to cleaning up related
> >>> code (patches 2/3 and 3/3).
> >>> 
> >>> The first patch is a regression fix and should thus be merged before
> >>> v4.19. The other two patches can wait until v4.20.
> >> 
> >> Hmm can you please check again with this patch applied:
> >> 
> >> "[PATCH] mfd: omap-usb-host: Fix dts probe of children"
> > 
> > This fixes the issue for me.
> > 
> > Tested-by: Laurent Pinchart 
> 
> OK good to hear.

The fix is still not in v4.19-rc4 :-S Could you make sure it doesn't miss 
v4.19 ?

> >> That was supposed to be queued for v4.18 but fell through the
> >> cracks and I only recently noticed it but Lee has it tagged
> >> now for v4.19-rc series.
> >> 
> >> But maybe there are additional issues..
> > 
> > I think we can go one step further and avoid using fs_initcall, but that
> > can wait for v4.20. What's your opinion on that ? If you agree I'll
> > resubmit this series rebased on top of the aforementioned patch.
> 
> Yes sounds good to me. Actually with ti-sysc we're probing the
> interconnect target modules at module_init time, so any children
> will only get probed after that and the fs_initcall is not
> doing anything before that mhuwhhaa.
> 
> But yeah hopefully the fs_initcall is no longer needed with
> device tree based booting even before we have all the dts
> files using ti-sysc.
> 
> >>> Tony, as patch 1/3 fixes a problem introduced by one of your DT
> >>> changes,
> >>> could you please review it ? Out of curiosity, is ethernet on the
> >>> Pandaboard not part of your regression tests ?
> >> 
> >> Sorry not any longer.. I've switched over to wlan based
> >> setup for PM testing:
> >> 
> >> 1. u-boot downloads kernel dtb and modules.tar.gz and writes
> >>modules.tar.gz to MMC card
> >> 
> >> 2. on kernel boot, first modules.tar.gz is unpacked
> >> 
> >> 3. distro brings up wlan but no USB ether
> >> 
> >> So I can now test also PM on pandaboard-es. I do have ohci
> >> enabled on droid4 though for mdm6600 modem, but usually have
> >> ehci disabled as the w3glte modem on ehci does not yet work
> >> with mainline kernel.
> >
> > :-/ If you have a test script that analyzes the kernel log, it would be
> > useful to add a check to verify that the USB ethernet interface chip is
> > detected. That would prevent the regression we're seeing here.
> 
> Yeah sorry about the regression.
> 
> Hrm well it goes back to the droid4 lcd patches again that I've
> been carrying along :) I did not notice this was still pending
> too buried into the pile I was carrying until recently.. The
> original fix was already sent back in April.
> 
> I in fact worked all summer using Linux next (working) snapshots
> on droid4 with a lapdock over ssh and mdm6600 modem on it's ohci
> bus being my main connection. So the *hci is getting tested by
> real use in this case, no need to analyze kernel logs unless
> something goes wrong.

-- 
Regards,

Laurent Pinchart





[PATCH 2/4] usb: gadget: uvc: configfs: Fix operation on big endian platforms

2018-09-18 Thread Laurent Pinchart
USB descriptors are stored in little endian, requiring the use of
conversion macros. Those macros are incorrectly used for values stored
in native endian structures within the driver. Operation on big endian
platforms is thus broken. Fix it by removing the conversion macros where
they're not needed.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_configfs.c | 59 --
 1 file changed, 24 insertions(+), 35 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 6031467f1868..522cb7be9850 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1105,7 +1105,7 @@ static struct uvcg_frame *to_uvcg_frame(struct 
config_item *item)
return container_of(item, struct uvcg_frame, item);
 }
 
-#define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
+#define UVCG_FRAME_ATTR(cname, aname, bits) \
 static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
 {  \
struct uvcg_frame *f = to_uvcg_frame(item); \
@@ -1120,7 +1120,7 @@ static ssize_t uvcg_frame_##cname##_show(struct 
config_item *item, char *page)\
opts = to_f_uvc_opts(opts_item);\
\
mutex_lock(>lock);\
-   result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname));  \
+   result = sprintf(page, "%d\n", f->frame.cname); \
mutex_unlock(>lock);  \
\
mutex_unlock(su_mutex); \
@@ -1154,7 +1154,7 @@ static ssize_t  uvcg_frame_##cname##_store(struct 
config_item *item,  \
goto end;   \
}   \
\
-   f->frame.cname = to_little_endian(num); \
+   f->frame.cname = num;   \
ret = len;  \
 end:   \
mutex_unlock(>lock);  \
@@ -1199,20 +1199,13 @@ static ssize_t uvcg_frame_b_frame_index_show(struct 
config_item *item,
 
 UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
 
-#define noop_conversion(x) (x)
-
-UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
-   noop_conversion, 8);
-UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
-UVCG_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16);
-UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32, 32);
-UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, le32_to_cpu, cpu_to_le32, 32);
-UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize,
-   le32_to_cpu, cpu_to_le32, 32);
-UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval,
-   le32_to_cpu, cpu_to_le32, 32);
-
-#undef noop_conversion
+UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, 8);
+UVCG_FRAME_ATTR(w_width, wWidth, 16);
+UVCG_FRAME_ATTR(w_height, wHeight, 16);
+UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32);
+UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32);
+UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32);
+UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32);
 
 #undef UVCG_FRAME_ATTR
 
@@ -1233,8 +1226,7 @@ static ssize_t uvcg_frame_dw_frame_interval_show(struct 
config_item *item,
 
mutex_lock(>lock);
for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
-   result += sprintf(pg, "%d\n",
- le32_to_cpu(frm->dw_frame_interval[i]));
+   result += sprintf(pg, "%d\n", frm->dw_frame_interval[i]);
pg = page + result;
}
mutex_unlock(>lock);
@@ -1259,7 +1251,7 @@ static inline int __uvcg_fill_frm_intrv(char *buf, void 
*priv)
return ret;
 
interv = priv;
-   **interv = cpu_to_le32(num);
+   **interv = num;
++*interv;
 
return 0;
@@ -1381,12 +1373,12 @@ static struct config_item *uvcg_frame_make(struct 
config_group *group,
 
h->frame.b_descriptor_type  = USB_DT_CS_INTERFACE;
h->frame.b_frame_index  = 1;
-   h->frame.w_width= cpu_to_le16(640);
-   h->frame.w_height 

[PATCH 0/4] usb: gadget: uvc: Fix endianness and sign issues

2018-09-18 Thread Laurent Pinchart
Hello,

This series addresses endianness and sign issues in the configfs support
of the UVC gadget function driver.

The first patch starts by fixing the endianness of various UVC
descriptors to match the USB little endian order. The second patch then
fixed the UVC gadget function driver to handle endianness correctly when
parsing configfs attributes.

The next patch goes on to simplify UVC configfs attribute macros, and
the last patch finally fixes sign issues by using the correct format to
print unsigned int values.

Laurent Pinchart (4):
  usb: video: Fix endianness mismatches in descriptor structures
  usb: gadget: uvc: configfs: Fix operation on big endian platforms
  usb: gadget: uvc: configfs: Simplify attributes macros
  usb: gadget: uvc: configfs: Use %u to print unsigned int values

 drivers/usb/gadget/function/uvc_configfs.c | 241 +--
 include/uapi/linux/usb/video.h | 304 ++---
 2 files changed, 249 insertions(+), 296 deletions(-)

-- 
Regards,

Laurent Pinchart



[PATCH 1/4] usb: video: Fix endianness mismatches in descriptor structures

2018-09-18 Thread Laurent Pinchart
All UVC descriptors use little-endian format, update the data structures
accordingly.

Signed-off-by: Laurent Pinchart 
---
 include/uapi/linux/usb/video.h | 304 -
 1 file changed, 152 insertions(+), 152 deletions(-)

diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h
index ff6cc6cb4227..d854cb19c42c 100644
--- a/include/uapi/linux/usb/video.h
+++ b/include/uapi/linux/usb/video.h
@@ -192,14 +192,14 @@ struct uvc_descriptor_header {
 
 /* 3.7.2. Video Control Interface Header Descriptor */
 struct uvc_header_descriptor {
-   __u8  bLength;
-   __u8  bDescriptorType;
-   __u8  bDescriptorSubType;
-   __u16 bcdUVC;
-   __u16 wTotalLength;
-   __u32 dwClockFrequency;
-   __u8  bInCollection;
-   __u8  baInterfaceNr[];
+   __u8   bLength;
+   __u8   bDescriptorType;
+   __u8   bDescriptorSubType;
+   __le16 bcdUVC;
+   __le16 wTotalLength;
+   __le32 dwClockFrequency;
+   __u8   bInCollection;
+   __u8   baInterfaceNr[];
 } __attribute__((__packed__));
 
 #define UVC_DT_HEADER_SIZE(n)  (12+(n))
@@ -209,57 +209,57 @@ struct uvc_header_descriptor {
 
 #define DECLARE_UVC_HEADER_DESCRIPTOR(n)   \
 struct UVC_HEADER_DESCRIPTOR(n) {  \
-   __u8  bLength;  \
-   __u8  bDescriptorType;  \
-   __u8  bDescriptorSubType;   \
-   __u16 bcdUVC;   \
-   __u16 wTotalLength; \
-   __u32 dwClockFrequency; \
-   __u8  bInCollection;\
-   __u8  baInterfaceNr[n]; \
+   __u8   bLength; \
+   __u8   bDescriptorType; \
+   __u8   bDescriptorSubType;  \
+   __le16 bcdUVC;  \
+   __le16 wTotalLength;\
+   __le32 dwClockFrequency;\
+   __u8   bInCollection;   \
+   __u8   baInterfaceNr[n];\
 } __attribute__ ((packed))
 
 /* 3.7.2.1. Input Terminal Descriptor */
 struct uvc_input_terminal_descriptor {
-   __u8  bLength;
-   __u8  bDescriptorType;
-   __u8  bDescriptorSubType;
-   __u8  bTerminalID;
-   __u16 wTerminalType;
-   __u8  bAssocTerminal;
-   __u8  iTerminal;
+   __u8   bLength;
+   __u8   bDescriptorType;
+   __u8   bDescriptorSubType;
+   __u8   bTerminalID;
+   __le16 wTerminalType;
+   __u8   bAssocTerminal;
+   __u8   iTerminal;
 } __attribute__((__packed__));
 
 #define UVC_DT_INPUT_TERMINAL_SIZE 8
 
 /* 3.7.2.2. Output Terminal Descriptor */
 struct uvc_output_terminal_descriptor {
-   __u8  bLength;
-   __u8  bDescriptorType;
-   __u8  bDescriptorSubType;
-   __u8  bTerminalID;
-   __u16 wTerminalType;
-   __u8  bAssocTerminal;
-   __u8  bSourceID;
-   __u8  iTerminal;
+   __u8   bLength;
+   __u8   bDescriptorType;
+   __u8   bDescriptorSubType;
+   __u8   bTerminalID;
+   __le16 wTerminalType;
+   __u8   bAssocTerminal;
+   __u8   bSourceID;
+   __u8   iTerminal;
 } __attribute__((__packed__));
 
 #define UVC_DT_OUTPUT_TERMINAL_SIZE9
 
 /* 3.7.2.3. Camera Terminal Descriptor */
 struct uvc_camera_terminal_descriptor {
-   __u8  bLength;
-   __u8  bDescriptorType;
-   __u8  bDescriptorSubType;
-   __u8  bTerminalID;
-   __u16 wTerminalType;
-   __u8  bAssocTerminal;
-   __u8  iTerminal;
-   __u16 wObjectiveFocalLengthMin;
-   __u16 wObjectiveFocalLengthMax;
-   __u16 wOcularFocalLength;
-   __u8  bControlSize;
-   __u8  bmControls[3];
+   __u8   bLength;
+   __u8   bDescriptorType;
+   __u8   bDescriptorSubType;
+   __u8   bTerminalID;
+   __le16 wTerminalType;
+   __u8   bAssocTerminal;
+   __u8   iTerminal;
+   __le16 wObjectiveFocalLengthMin;
+   __le16 wObjectiveFocalLengthMax;
+   __le16 wOcularFocalLength;
+   __u8   bControlSize;
+   __u8   bmControls[3];
 } __attribute__((__packed__));
 
 #define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n))
@@ -293,15 +293,15 @@ struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) {  \
 
 /* 3.7.2.5. Processing Unit Descriptor */
 struct uvc_processing_unit_descriptor {
-   __u8  bLength;
-   __u8  bDescriptorType;
-   __u8  bDescriptorSubType;
-   __u8  bUnitID;
-   __u8  bSourceID;
-   __u16 wMaxMultiplier;
-   __u8  bControlSize;
-   __u8  bmControls[2];
-   __u8  iProcessing;
+   __u8   bLength;
+   __u8   bDescriptorType;
+   __u8   bDescriptorSubType;
+   __u8   bUnitID;
+   __u8   bSourceID

[PATCH 4/4] usb: gadget: uvc: configfs: Use %u to print unsigned int values

2018-09-18 Thread Laurent Pinchart
The driver uses the %d format to print unsigned int values. The correct
format is %u. Fix it.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_configfs.c | 32 +++---
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 36f8f03e25e4..bc1e2af566c3 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -154,7 +154,7 @@ static ssize_t uvcg_control_header_##cname##_show(  
\
opts = to_f_uvc_opts(opts_item);\
\
mutex_lock(>lock);\
-   result = sprintf(page, "%d\n", le##bits##_to_cpu(ch->desc.aname));\
+   result = sprintf(page, "%u\n", le##bits##_to_cpu(ch->desc.aname));\
mutex_unlock(>lock);  \
\
mutex_unlock(su_mutex); \
@@ -274,7 +274,7 @@ static ssize_t uvcg_default_processing_##cname##_show(  
\
pd = >uvc_processing; \
\
mutex_lock(>lock);\
-   result = sprintf(page, "%d\n", le##bits##_to_cpu(pd->aname));   \
+   result = sprintf(page, "%u\n", le##bits##_to_cpu(pd->aname));   \
mutex_unlock(>lock);  \
\
mutex_unlock(su_mutex); \
@@ -309,7 +309,7 @@ static ssize_t uvcg_default_processing_bm_controls_show(
 
mutex_lock(>lock);
for (result = 0, i = 0; i < pd->bControlSize; ++i) {
-   result += sprintf(pg, "%d\n", pd->bmControls[i]);
+   result += sprintf(pg, "%u\n", pd->bmControls[i]);
pg = page + result;
}
mutex_unlock(>lock);
@@ -378,7 +378,7 @@ static ssize_t uvcg_default_camera_##cname##_show(  
\
cd = >uvc_camera_terminal;\
\
mutex_lock(>lock);\
-   result = sprintf(page, "%d\n", le##bits##_to_cpu(cd->aname));   \
+   result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname));   \
mutex_unlock(>lock);  \
\
mutex_unlock(su_mutex); \
@@ -421,7 +421,7 @@ static ssize_t uvcg_default_camera_bm_controls_show(
 
mutex_lock(>lock);
for (result = 0, i = 0; i < cd->bControlSize; ++i) {
-   result += sprintf(pg, "%d\n", cd->bmControls[i]);
+   result += sprintf(pg, "%u\n", cd->bmControls[i]);
pg = page + result;
}
mutex_unlock(>lock);
@@ -492,7 +492,7 @@ static ssize_t uvcg_default_output_##cname##_show(  
\
cd = >uvc_output_terminal;\
\
mutex_lock(>lock);\
-   result = sprintf(page, "%d\n", le##bits##_to_cpu(cd->aname));   \
+   result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname));   \
mutex_unlock(>lock);  \
\
mutex_unlock(su_mutex); \
@@ -995,7 +995,7 @@ static ssize_t uvcg_streaming_header_##cname##_show(
\
opts = to_f_uvc_opts(opts_item);\
\
mutex_lock(>lock);\
-   result = sprintf(page, "%d\n", le##bits##_to_cpu(sh->desc.aname));\
+   result = sprintf(page, "%u\n", le##bits##_to_cpu(sh->desc.aname));\
mutex_unlock(>lock);  \
\
mutex_unlock(su_mutex); \
@@ -1104,7 +1104,7 @@ static ssize_t uvcg_frame_##cname##_show(struct 
config_item *item, char *page)\
opts = to_f_uvc_

[PATCH 3/4] usb: gadget: uvc: configfs: Simplify attributes macros

2018-09-18 Thread Laurent Pinchart
Several macros used to define attributes and their access functions take
multiple arguments to specify endianness and string conversion
functions, based on the size of the attribute. This can be simplified by
passing the number of bits explicitly, and constructing the name of the
functions internally.

The UVCG_OPTS_ATTR macro can be simplified further as all fields it
deals with are unsigned int.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_configfs.c | 184 -
 1 file changed, 74 insertions(+), 110 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 522cb7be9850..36f8f03e25e4 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -38,6 +38,9 @@ static struct configfs_attribute prefix##attr_##cname = { \
.show   = prefix##cname##_show, \
 }
 
+#define le8_to_cpu(x)  (x)
+#define cpu_to_le8(x)  (x)
+
 static int uvcg_config_compare_u32(const void *l, const void *r)
 {
u32 li = *(const u32 *)l;
@@ -135,9 +138,9 @@ static struct uvcg_control_header 
*to_uvcg_control_header(struct config_item *it
return container_of(item, struct uvcg_control_header, item);
 }
 
-#define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit)
\
+#define UVCG_CTRL_HDR_ATTR(cname, aname, bits, limit)  \
 static ssize_t uvcg_control_header_##cname##_show( \
-   struct config_item *item, char *page)   \
+   struct config_item *item, char *page)   \
 {  \
struct uvcg_control_header *ch = to_uvcg_control_header(item);  \
struct f_uvc_opts *opts;\
@@ -151,7 +154,7 @@ static ssize_t uvcg_control_header_##cname##_show(  
\
opts = to_f_uvc_opts(opts_item);\
\
mutex_lock(>lock);\
-   result = sprintf(page, "%d\n", conv(ch->desc.aname));   \
+   result = sprintf(page, "%d\n", le##bits##_to_cpu(ch->desc.aname));\
mutex_unlock(>lock);  \
\
mutex_unlock(su_mutex); \
@@ -167,7 +170,7 @@ uvcg_control_header_##cname##_store(struct config_item 
*item,   \
struct config_item *opts_item;  \
struct mutex *su_mutex = >item.ci_group->cg_subsys->su_mutex;\
int ret;\
-   uxx num;\
+   u##bits num;\
\
mutex_lock(su_mutex); /* for navigating configfs hierarchy */   \
\
@@ -180,7 +183,7 @@ uvcg_control_header_##cname##_store(struct config_item 
*item,   \
goto end;   \
}   \
\
-   ret = str2u(page, 0, ); \
+   ret = kstrtou##bits(page, 0, ); \
if (ret)\
goto end;   \
\
@@ -188,7 +191,7 @@ uvcg_control_header_##cname##_store(struct config_item 
*item,   \
ret = -EINVAL;  \
goto end;   \
}   \
-   ch->desc.aname = vnoc(num); \
+   ch->desc.aname = cpu_to_le##bits(num);  \
ret = len;  \
 end:   \
mutex_unlock(>lock);  \
@@ -198,11 +201,9 @@ end:   
\
\
 UVC_ATTR(uvcg_control_header_, cname, aname)
 
-UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, le16_to_cpu, kstrtou16, u16, cpu_to_le16,
-

[PATCH] usb: gadget: uvc: Remove uvc_set_trace_param() function

2018-09-18 Thread Laurent Pinchart
The function is never called, remove it.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/f_uvc.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uvc.c 
b/drivers/usb/gadget/function/f_uvc.c
index 0cc4a6220050..8c99392df593 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -197,12 +197,6 @@ static const struct usb_descriptor_header * const 
uvc_ss_streaming[] = {
NULL,
 };
 
-void uvc_set_trace_param(unsigned int trace)
-{
-   uvc_gadget_trace_param = trace;
-}
-EXPORT_SYMBOL(uvc_set_trace_param);
-
 /* --
  * Control requests
  */
-- 
Regards,

Laurent Pinchart



[PATCH 2/3] usb: gadget: uvc: Only halt video streaming endpoint in bulk mode

2018-09-18 Thread Laurent Pinchart
When USB requests for video data fail to be submitted, the driver
signals a problem to the host by halting the video streaming endpoint.
This is only valid in bulk mode, as isochronous transfers have no
handshake phase and can't thus report a stall. The usb_ep_set_halt()
call returns an error when using isochronous endpoints, which we happily
ignore, but some UDCs complain in the kernel log. Fix this by only
trying to halt the endpoint in bulk mode.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_video.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/uvc_video.c 
b/drivers/usb/gadget/function/uvc_video.c
index a95c8e2364ed..2c9821ec836e 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -132,7 +132,9 @@ static int uvcg_video_ep_queue(struct uvc_video *video, 
struct usb_request *req)
ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
if (ret < 0) {
printk(KERN_INFO "Failed to queue request (%d).\n", ret);
-   usb_ep_set_halt(video->ep);
+   /* Isochronous endpoints can't be halted. */
+   if (usb_endpoint_xfer_bulk(video->ep->desc))
+   usb_ep_set_halt(video->ep);
}
 
    return ret;
-- 
Regards,

Laurent Pinchart



[PATCH 3/3] usb: gadget: uvc: Replace plain printk() with dev_*()

2018-09-18 Thread Laurent Pinchart
Adding device context to the kernel log messages make them more useful.
Add new uvcg_* macros based on dev_*() that print both the gadget device
name and the function name.

While at it, remove a commented out printk statement and an unused
printk-based macro.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/f_uvc.c | 41 ++---
 drivers/usb/gadget/function/uvc.h   | 16 ++---
 drivers/usb/gadget/function/uvc_v4l2.c  |  4 ++--
 drivers/usb/gadget/function/uvc_video.c | 18 +--
 drivers/usb/gadget/function/uvc_video.h |  2 +-
 5 files changed, 39 insertions(+), 42 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uvc.c 
b/drivers/usb/gadget/function/f_uvc.c
index 4ea987741e6e..0cc4a6220050 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -232,13 +232,8 @@ uvc_function_setup(struct usb_function *f, const struct 
usb_ctrlrequest *ctrl)
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)_event.u.data;
 
-   /* printk(KERN_INFO "setup request %02x %02x value %04x index %04x 
%04x\n",
-*  ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue),
-*  le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength));
-*/
-
if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) {
-   INFO(f->config->cdev, "invalid request type\n");
+   uvcg_info(f, "invalid request type\n");
return -EINVAL;
}
 
@@ -272,7 +267,7 @@ uvc_function_get_alt(struct usb_function *f, unsigned 
interface)
 {
struct uvc_device *uvc = to_uvc(f);
 
-   INFO(f->config->cdev, "uvc_function_get_alt(%u)\n", interface);
+   uvcg_info(f, "%s(%u)\n", __func__, interface);
 
if (interface == uvc->control_intf)
return 0;
@@ -291,13 +286,13 @@ uvc_function_set_alt(struct usb_function *f, unsigned 
interface, unsigned alt)
struct uvc_event *uvc_event = (void *)_event.u.data;
int ret;
 
-   INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
+   uvcg_info(f, "%s(%u, %u)\n", __func__, interface, alt);
 
if (interface == uvc->control_intf) {
if (alt)
return -EINVAL;
 
-   INFO(cdev, "reset UVC Control\n");
+   uvcg_info(f, "reset UVC Control\n");
usb_ep_disable(uvc->control_ep);
 
if (!uvc->control_ep->desc)
@@ -348,7 +343,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned 
interface, unsigned alt)
if (!uvc->video.ep)
return -EINVAL;
 
-   INFO(cdev, "reset UVC\n");
+   uvcg_info(f, "reset UVC\n");
usb_ep_disable(uvc->video.ep);
 
ret = config_ep_by_speed(f->config->cdev->gadget,
@@ -373,7 +368,7 @@ uvc_function_disable(struct usb_function *f)
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
 
-   INFO(f->config->cdev, "uvc_function_disable\n");
+   uvcg_info(f, "%s()\n", __func__);
 
memset(_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_DISCONNECT;
@@ -392,21 +387,19 @@ uvc_function_disable(struct usb_function *f)
 void
 uvc_function_connect(struct uvc_device *uvc)
 {
-   struct usb_composite_dev *cdev = uvc->func.config->cdev;
int ret;
 
if ((ret = usb_function_activate(>func)) < 0)
-   INFO(cdev, "UVC connect failed with %d\n", ret);
+   uvcg_info(>func, "UVC connect failed with %d\n", ret);
 }
 
 void
 uvc_function_disconnect(struct uvc_device *uvc)
 {
-   struct usb_composite_dev *cdev = uvc->func.config->cdev;
int ret;
 
if ((ret = usb_function_deactivate(>func)) < 0)
-   INFO(cdev, "UVC disconnect failed with %d\n", ret);
+   uvcg_info(>func, "UVC disconnect failed with %d\n", ret);
 }
 
 /* --
@@ -605,7 +598,7 @@ uvc_function_bind(struct usb_configuration *c, struct 
usb_function *f)
struct f_uvc_opts *opts;
int ret = -EINVAL;
 
-   INFO(cdev, "uvc_function_bind\n");
+   uvcg_info(f, "%s()\n", __func__);
 
opts = fi_to_f_uvc_opts(f->fi);
/* Sanity check the streaming endpoint module parameters.
@@ -618,8 +611,8 @@ uvc_function_bind(struct usb_configuration *c, struct 
usb_function *f)
if (opts->streaming_maxburst &&
(opts->streaming_maxpacket % 1024) != 0) {
opts->streaming_maxpacket = roundup(opts->streaming_maxpacke

[PATCH 1/3] usb: gadget: uvc: Factor out video USB request queueing

2018-09-18 Thread Laurent Pinchart
USB requests for video data are queued from two different locations in
the driver, with the same code block occurring twice. Factor it out to a
function.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_video.c | 30 --
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_video.c 
b/drivers/usb/gadget/function/uvc_video.c
index d3567b90343a..a95c8e2364ed 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -125,6 +125,19 @@ uvc_video_encode_isoc(struct usb_request *req, struct 
uvc_video *video,
  * Request handling
  */
 
+static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request 
*req)
+{
+   int ret;
+
+   ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
+   if (ret < 0) {
+   printk(KERN_INFO "Failed to queue request (%d).\n", ret);
+   usb_ep_set_halt(video->ep);
+   }
+
+   return ret;
+}
+
 /*
  * I somehow feel that synchronisation won't be easy to achieve here. We have
  * three events that control USB requests submission:
@@ -189,14 +202,13 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request 
*req)
 
video->encode(req, video, buf);
 
-   if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) {
-   printk(KERN_INFO "Failed to queue request (%d).\n", ret);
-   usb_ep_set_halt(ep);
-   spin_unlock_irqrestore(>queue.irqlock, flags);
+   ret = uvcg_video_ep_queue(video, req);
+   spin_unlock_irqrestore(>queue.irqlock, flags);
+
+   if (ret < 0) {
uvcg_queue_cancel(queue, 0);
goto requeue;
}
-   spin_unlock_irqrestore(>queue.irqlock, flags);
 
return;
 
@@ -316,15 +328,13 @@ int uvcg_video_pump(struct uvc_video *video)
video->encode(req, video, buf);
 
/* Queue the USB request */
-   ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
+   ret = uvcg_video_ep_queue(video, req);
+   spin_unlock_irqrestore(>irqlock, flags);
+
if (ret < 0) {
-   printk(KERN_INFO "Failed to queue request (%d)\n", ret);
-   usb_ep_set_halt(video->ep);
-   spin_unlock_irqrestore(>irqlock, flags);
uvcg_queue_cancel(queue, 0);
break;
}
-   spin_unlock_irqrestore(>irqlock, flags);
    }
 
spin_lock_irqsave(>req_lock, flags);
-- 
Regards,

Laurent Pinchart



[PATCH] usb: gadget: uvc: configfs: Sort frame intervals upon writing

2018-09-18 Thread Laurent Pinchart
From: Paul Elder 

There is an issue where the host is unable to tell the gadget what frame
rate it wants if the dwFrameIntervals in the interface descriptors are
not in ascending order. This means that when instantiating a uvc gadget
via configfs the user must make sure the dwFrameIntervals are in
ascending order.

Instead of silently failing the breaking of this rule, we sort the
dwFrameIntervals upon writing to configfs.

Signed-off-by: Paul Elder 
Reviewed-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_configfs.c | 13 +
 1 file changed, 13 insertions(+)

This patch applies on top of the "[PATCH v2 0/8] usb: gadget: uvc: Improve
configfs support" series previously posted.

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 799dc32c5bc7..6031467f1868 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -9,6 +9,9 @@
  *
  * Author: Andrzej Pietrasiewicz 
  */
+
+#include 
+
 #include "u_uvc.h"
 #include "uvc_configfs.h"
 
@@ -35,6 +38,14 @@ static struct configfs_attribute prefix##attr_##cname = { \
.show   = prefix##cname##_show, \
 }
 
+static int uvcg_config_compare_u32(const void *l, const void *r)
+{
+   u32 li = *(const u32 *)l;
+   u32 ri = *(const u32 *)r;
+
+   return li < ri ? -1 : li == ri ? 0 : 1;
+}
+
 static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
 {
return container_of(to_config_group(item), struct f_uvc_opts,
@@ -1325,6 +1336,8 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct 
config_item *item,
kfree(ch->dw_frame_interval);
ch->dw_frame_interval = frm_intrv;
ch->frame.b_frame_interval_type = n;
+   sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval),
+uvcg_config_compare_u32, NULL);
    ret = len;
 
 end:
-- 
Regards,

Laurent Pinchart



Re: [PATCH 3/3] mfd: omap-usb-host: Drop support for non-DT probe

2018-09-12 Thread Laurent Pinchart
Hi Roger,

On Wednesday, 12 September 2018 10:57:31 EEST Roger Quadros wrote:
> On 11/09/18 18:06, Laurent Pinchart wrote:
> > Now that all platforms using OMAP USB host devices have been converted
> > to DT, drop support for legacy non-DT probe from the driver.
> > 
> > Signed-off-by: Laurent Pinchart 
> > ---
> > 
> >  drivers/mfd/omap-usb-host.c| 153 ++--
> >  include/linux/platform_data/usb-omap.h |   4 -
> >  2 files changed, 13 insertions(+), 144 deletions(-)
> > 
> > diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
> > index b731026541f5..ce28e0fda55e 100644
> > --- a/drivers/mfd/omap-usb-host.c
> > +++ b/drivers/mfd/omap-usb-host.c

[snip]

> > @@ -541,31 +424,28 @@ static const struct of_device_id
> > usbhs_child_match_table[] = {
> >  static int usbhs_omap_probe(struct platform_device *pdev)
> >  {
> > struct device   *dev =  >dev;
> > -   struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
> > +   struct usbhs_omap_platform_data *pdata;
> > struct usbhs_hcd_omap   *omap;
> > struct resource *res;
> > int ret = 0;
> > int i;
> > boolneed_logic_fck;
> > 
> > -   dev_info(>dev, "%s\n", __func__);
> > -   if (dev->of_node) {
> > -   /* For DT boot we populate platform data from OF node */
> > -   pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> > -   if (!pdata)
> > -   return -ENOMEM;
> > +   /* Populate platform data from OF node */
> > +   if (!dev->of_node) {
> > +   dev_err(dev, "Missing OF node\n");
> > +   return -ENODEV;
> > +   }
> > 
> > -   ret = usbhs_omap_get_dt_pdata(dev, pdata);
> > -   if (ret)
> > -   return ret;
> > +   pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> > +   if (!pdata)
> > +   return -ENOMEM;
> > 
> > -   dev->platform_data = pdata;
> > -   }
> > +   ret = usbhs_omap_get_dt_pdata(dev, pdata);
> > +   if (ret)
> > +   return ret;
> > 
> > -   if (!pdata) {
> > -   dev_err(dev, "Missing platform data\n");
> > -   return -ENODEV;
> > -   }
> > +   dev->platform_data = pdata;
> 
> Do we still need to set dev->platform_data?
> 
> This driver can access it via
>   struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
>   omap->pdata;

Unfortunately we still do, as the ehci-omap driver accesses the omap-usb-host 
device platform data (through the ehci-omap device's parent).

> > if (pdata->nports > OMAP3_HS_USB_PORTS) {
> > dev_info(dev, "Too many num_ports <%d> in platform_data. Max 
> > %d\n",
> > 
> > @@ -798,13 +678,6 @@ static int usbhs_omap_probe(struct platform_device
> > *pdev)
> > goto err_mem;
> > }
> > -   } else {
> > -   ret = omap_usbhs_alloc_children(pdev);
> > -   if (ret) {
> > -   dev_err(dev, "omap_usbhs_alloc_children failed: %d\n",
> > -   ret);
> > -   goto err_mem;
> > -   }
> > }
> > 
> > return 0;

[snip]

-- 
Regards,

Laurent Pinchart





Re: [PATCH 1/3] mfd: omap-usb-host: Use regular platform device probe mechanism

2018-09-11 Thread Laurent Pinchart
On Tuesday, 11 September 2018 18:53:19 EEST Ladislav Michl wrote:
> On Tue, Sep 11, 2018 at 06:06:08PM +0300, Laurent Pinchart wrote:
> > The omap-usb-host driver uses platform_driver_probe() in the fs initcall
> > level to ensure that the devices get probed before the EHCI and OHCI
> > drivers arer probed.
> > 
> > The EHCI and OHCI devices are created and registered by the omap-usb-host
> > driver, and if no driver is present yet to handle them they will
> > patiently wait for they turn without any adverse effect. This mechanism
> > is thus not needed, remove it.
> > 
> > This fixes a bug that prevents EHCI and OHCI devices from being probed
> > on the Pandaboard since commit 84badc5ec5fc ("ARM: dts: omap4: Move l4
> > child devices to probe them with ti-sysc"), as then omap-usb-host
> > devices are now registered after the omap-usb-host driver initializes,
> > and thus fail to probe due to platform_driver_probe() not finding any
> > device.
> > 
> > Fixes: 84badc5ec5fc ("ARM: dts: omap4: Move l4 child devices to probe them
> > with ti-sysc") Signed-off-by: Laurent Pinchart
> >  ---
> > 
> >  drivers/mfd/omap-usb-host.c | 24 
> >  1 file changed, 4 insertions(+), 20 deletions(-)
> > 
> > diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
> > index e11ab12fbdf2..b731026541f5 100644
> > --- a/drivers/mfd/omap-usb-host.c
> > +++ b/drivers/mfd/omap-usb-host.c
> > @@ -548,6 +548,7 @@ static int usbhs_omap_probe(struct platform_device
> > *pdev)> 
> > int i;
> > boolneed_logic_fck;
> > 
> > +   dev_info(>dev, "%s\n", __func__);
> 
> Is it indentional? Seems like debug leftover.

Clearly a debug leftover, sorry about that.

> > if (dev->of_node) {
> > 
> > /* For DT boot we populate platform data from OF node */
> > pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> > 
> > @@ -855,31 +856,14 @@ static struct platform_driver usbhs_omap_driver = {
> > 
> > .pm = _dev_pm_ops,
> > .of_match_table = usbhs_omap_dt_ids,
> > 
> > },
> > 
> > +   .probe  = usbhs_omap_probe,
> > 
> > .remove = usbhs_omap_remove,
> >  
> >  };
> > 
> > +module_platform_driver(usbhs_omap_driver);
> > +
> > 
> >  MODULE_AUTHOR("Keshava Munegowda ");
> >  MODULE_AUTHOR("Roger Quadros ");
> >  MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
> >  MODULE_LICENSE("GPL v2");
> >  MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
> > 
> > -
> > -static int __init omap_usbhs_drvinit(void)
> > -{
> > -   return platform_driver_probe(_omap_driver, usbhs_omap_probe);
> > -}
> > -
> > -/*
> > - * init before ehci and ohci drivers;
> > - * The usbhs core driver should be initialized much before
> > - * the omap ehci and ohci probe functions are called.
> > - * This usbhs core driver should be initialized after
> > - * usb tll driver
> > - */
> > -fs_initcall_sync(omap_usbhs_drvinit);
> > -
> > -static void __exit omap_usbhs_drvexit(void)
> > -{
> > -   platform_driver_unregister(_omap_driver);
> > -}
> > -module_exit(omap_usbhs_drvexit);

-- 
Regards,

Laurent Pinchart





Re: [PATCH 0/3] Fix OMAP EHCI probe & assorted cleanups

2018-09-11 Thread Laurent Pinchart
Hi Tony,

On Tuesday, 11 September 2018 18:16:41 EEST Tony Lindgren wrote:
> * Laurent Pinchart  [180911 15:10]:
> > Hello,
> > 
> > This series fixes a v4.19-rc1 regression that results in OMAP EHCI failing
> > to probe (patch 1/3) and then moves on to cleaning up related code
> > (patches 2/3 and 3/3).
> > 
> > The first patch is a regression fix and should thus be merged before
> > v4.19. The other two patches can wait until v4.20.
> 
> Hmm can you please check again with this patch applied:
> 
> "[PATCH] mfd: omap-usb-host: Fix dts probe of children"

This fixes the issue for me.

Tested-by: Laurent Pinchart 

> That was supposed to be queued for v4.18 but fell through the
> cracks and I only recently noticed it but Lee has it tagged
> now for v4.19-rc series.
> 
> But maybe there are additional issues..

I think we can go one step further and avoid using fs_initcall, but that can 
wait for v4.20. What's your opinion on that ? If you agree I'll resubmit this 
series rebased on top of the aforementioned patch.

> > Tony, as patch 1/3 fixes a problem introduced by one of your DT changes,
> > could you please review it ? Out of curiosity, is ethernet on the
> > Pandaboard not part of your regression tests ?
> 
> Sorry not any longer.. I've switched over to wlan based
> setup for PM testing:
> 
> 1. u-boot downloads kernel dtb and modules.tar.gz and writes
>modules.tar.gz to MMC card
> 
> 2. on kernel boot, first modules.tar.gz is unpacked
> 
> 3. distro brings up wlan but no USB ether
> 
> So I can now test also PM on pandaboard-es. I do have ohci
> enabled on droid4 though for mdm6600 modem, but usually have
> ehci disabled as the w3glte modem on ehci does not yet work
> with mainline kernel.

:-/ If you have a test script that analyzes the kernel log, it would be useful 
to add a check to verify that the USB ethernet interface chip is detected. 
That would prevent the regression we're seeing here.

> > Lee, could you then please make sure the patch gets to mainline before
> > v4.19 final ?
> 
> Let's first check what all is needed, I'll test here too.

-- 
Regards,

Laurent Pinchart





[PATCH 3/3] mfd: omap-usb-host: Drop support for non-DT probe

2018-09-11 Thread Laurent Pinchart
Now that all platforms using OMAP USB host devices have been converted
to DT, drop support for legacy non-DT probe from the driver.

Signed-off-by: Laurent Pinchart 
---
 drivers/mfd/omap-usb-host.c| 153 +++--
 include/linux/platform_data/usb-omap.h |   4 -
 2 files changed, 13 insertions(+), 144 deletions(-)

diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index b731026541f5..ce28e0fda55e 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -23,7 +23,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -35,8 +34,6 @@
 #include "omap-usb.h"
 
 #define USBHS_DRIVER_NAME  "usbhs_omap"
-#define OMAP_EHCI_DEVICE   "ehci-omap"
-#define OMAP_OHCI_DEVICE   "ohci-omap3"
 
 /* OMAP USBHOST Register addresses  */
 
@@ -115,7 +112,6 @@ struct usbhs_hcd_omap {
 /*-*/
 
 static const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
-static u64 usbhs_dmamask = DMA_BIT_MASK(32);
 
 /*-*/
 
@@ -153,119 +149,6 @@ static const char * const port_modes[] = {
[OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM] = "ohci-tll-2pin-dpdm",
 };
 
-static struct platform_device *omap_usbhs_alloc_child(const char *name,
-   struct resource *res, int num_resources, void *pdata,
-   size_t pdata_size, struct device *dev)
-{
-   struct platform_device  *child;
-   int ret;
-
-   child = platform_device_alloc(name, 0);
-
-   if (!child) {
-   dev_err(dev, "platform_device_alloc %s failed\n", name);
-   goto err_end;
-   }
-
-   ret = platform_device_add_resources(child, res, num_resources);
-   if (ret) {
-   dev_err(dev, "platform_device_add_resources failed\n");
-   goto err_alloc;
-   }
-
-   ret = platform_device_add_data(child, pdata, pdata_size);
-   if (ret) {
-   dev_err(dev, "platform_device_add_data failed\n");
-   goto err_alloc;
-   }
-
-   child->dev.dma_mask = _dmamask;
-   dma_set_coherent_mask(>dev, DMA_BIT_MASK(32));
-   child->dev.parent   = dev;
-
-   ret = platform_device_add(child);
-   if (ret) {
-   dev_err(dev, "platform_device_add failed\n");
-   goto err_alloc;
-   }
-
-   return child;
-
-err_alloc:
-   platform_device_put(child);
-
-err_end:
-   return NULL;
-}
-
-static int omap_usbhs_alloc_children(struct platform_device *pdev)
-{
-   struct device   *dev = >dev;
-   struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
-   struct platform_device  *ehci;
-   struct platform_device  *ohci;
-   struct resource *res;
-   struct resource resources[2];
-   int ret;
-
-   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
-   if (!res) {
-   dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n");
-   ret = -ENODEV;
-   goto err_end;
-   }
-   resources[0] = *res;
-
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ehci-irq");
-   if (!res) {
-   dev_err(dev, " EHCI get resource IORESOURCE_IRQ failed\n");
-   ret = -ENODEV;
-   goto err_end;
-   }
-   resources[1] = *res;
-
-   ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, pdata,
-   sizeof(*pdata), dev);
-
-   if (!ehci) {
-   dev_err(dev, "omap_usbhs_alloc_child failed\n");
-   ret = -ENOMEM;
-   goto err_end;
-   }
-
-   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci");
-   if (!res) {
-   dev_err(dev, "OHCI get resource IORESOURCE_MEM failed\n");
-   ret = -ENODEV;
-   goto err_ehci;
-   }
-   resources[0] = *res;
-
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ohci-irq");
-   if (!res) {
-   dev_err(dev, "OHCI get resource IORESOURCE_IRQ failed\n");
-   ret = -ENODEV;
-   goto err_ehci;
-   }
-   resources[1] = *res;
-
-   ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, pdata,
-   sizeof(*pdata), dev);
-   if (!ohci) {
-   dev_err(dev, "omap_usbhs_alloc_child failed\n");
-   ret = -ENOMEM;
-   goto err_ehci;
-   }
-
-   return 0;
-
-err_ehci

[PATCH 2/3] ARM: OMAP2+: Remove legacy USB initialization code

2018-09-11 Thread Laurent Pinchart
Several legacy USB-related functions, structures and macros are not used
anymore after conversion to DT. Remove them.

Signed-off-by: Laurent Pinchart 
---
 arch/arm/mach-omap2/common.h|  2 -
 arch/arm/mach-omap2/omap_phy_internal.c | 96 +
 arch/arm/mach-omap2/usb.h   | 71 
 3 files changed, 2 insertions(+), 167 deletions(-)
 delete mode 100644 arch/arm/mach-omap2/usb.h

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 129455e822e4..7b561e07571e 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -40,8 +40,6 @@
 #include "i2c.h"
 #include "serial.h"
 
-#include "usb.h"
-
 #define OMAP_INTC_STARTNR_IRQS
 
 extern int (*omap_pm_soc_init)(void);
diff --git a/arch/arm/mach-omap2/omap_phy_internal.c 
b/arch/arm/mach-omap2/omap_phy_internal.c
index 8e903564ede2..456a883bbbda 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -23,17 +23,11 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include 
-#include 
-#include 
-#include 
 #include 
-#include 
-#include 
+#include 
+#include 
 
 #include "soc.h"
-#include "control.h"
-#include "usb.h"
 
 #define CONTROL_DEV_CONF   0x300
 #define PHY_PD 0x1
@@ -66,89 +60,3 @@ static int __init omap4430_phy_power_down(void)
return 0;
 }
 omap_early_initcall(omap4430_phy_power_down);
-
-void am35x_musb_reset(void)
-{
-   u32 regval;
-
-   /* Reset the musb interface */
-   regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
-
-   regval |= AM35XX_USBOTGSS_SW_RST;
-   omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
-
-   regval &= ~AM35XX_USBOTGSS_SW_RST;
-   omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
-
-   regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
-}
-
-void am35x_musb_phy_power(u8 on)
-{
-   unsigned long timeout = jiffies + msecs_to_jiffies(100);
-   u32 devconf2;
-
-   if (on) {
-   /*
-* Start the on-chip PHY and its PLL.
-*/
-   devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-   devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
-   devconf2 |= CONF2_PHY_PLLON;
-
-   omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-
-   pr_info("Waiting for PHY clock good...\n");
-   while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
-   & CONF2_PHYCLKGD)) {
-   cpu_relax();
-
-   if (time_after(jiffies, timeout)) {
-   pr_err("musb PHY clock good timed out\n");
-   break;
-   }
-   }
-   } else {
-   /*
-* Power down the on-chip PHY.
-*/
-   devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-   devconf2 &= ~CONF2_PHY_PLLON;
-   devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
-   omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-   }
-}
-
-void am35x_musb_clear_irq(void)
-{
-   u32 regval;
-
-   regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-   regval |= AM35XX_USBOTGSS_INT_CLR;
-   omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
-   regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-}
-
-void am35x_set_mode(u8 musb_mode)
-{
-   u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-   devconf2 &= ~CONF2_OTGMODE;
-   switch (musb_mode) {
-   case MUSB_HOST: /* Force VBUS valid, ID = 0 */
-   devconf2 |= CONF2_FORCE_HOST;
-   break;
-   case MUSB_PERIPHERAL:   /* Force VBUS valid, ID = 1 */
-   devconf2 |= CONF2_FORCE_DEVICE;
-   break;
-   case MUSB_OTG:  /* Don't override the VBUS/ID comparators */
-   devconf2 |= CONF2_NO_OVERRIDE;
-   break;
-   default:
-   pr_info("Unsupported mode %u\n", musb_mode);
-   }
-
-   omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-}
diff --git a/arch/arm/mach-omap2/usb.h b/arch/arm/mach-omap2/usb.h
deleted file mode 100644
index 740a499befce..
--- a/arch/arm/mach-omap2/usb.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include 
-
-/* AM35x */
-/* USB 2.0 PHY Control */
-#define CONF2_PHY_GPIOMODE (1 << 23)
-#define CONF2_OTGMODE  (3 << 14)
-#define CONF2_NO_OVERRIDE  (0 << 14)
-#define CONF2_FORCE_HOST   (1 << 14)
-#define CONF2_FORCE_DEVICE (2 << 14)
-#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
-#define CONF2_SES

[PATCH 1/3] mfd: omap-usb-host: Use regular platform device probe mechanism

2018-09-11 Thread Laurent Pinchart
The omap-usb-host driver uses platform_driver_probe() in the fs initcall
level to ensure that the devices get probed before the EHCI and OHCI
drivers arer probed.

The EHCI and OHCI devices are created and registered by the omap-usb-host
driver, and if no driver is present yet to handle them they will
patiently wait for they turn without any adverse effect. This mechanism
is thus not needed, remove it.

This fixes a bug that prevents EHCI and OHCI devices from being probed
on the Pandaboard since commit 84badc5ec5fc ("ARM: dts: omap4: Move l4
child devices to probe them with ti-sysc"), as then omap-usb-host
devices are now registered after the omap-usb-host driver initializes,
and thus fail to probe due to platform_driver_probe() not finding any
device.

Fixes: 84badc5ec5fc ("ARM: dts: omap4: Move l4 child devices to probe them with 
ti-sysc")
Signed-off-by: Laurent Pinchart 
---
 drivers/mfd/omap-usb-host.c | 24 
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index e11ab12fbdf2..b731026541f5 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -548,6 +548,7 @@ static int usbhs_omap_probe(struct platform_device *pdev)
int i;
boolneed_logic_fck;
 
+   dev_info(>dev, "%s\n", __func__);
if (dev->of_node) {
/* For DT boot we populate platform data from OF node */
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -855,31 +856,14 @@ static struct platform_driver usbhs_omap_driver = {
.pm = _dev_pm_ops,
.of_match_table = usbhs_omap_dt_ids,
},
+   .probe  = usbhs_omap_probe,
.remove = usbhs_omap_remove,
 };
 
+module_platform_driver(usbhs_omap_driver);
+
 MODULE_AUTHOR("Keshava Munegowda ");
 MODULE_AUTHOR("Roger Quadros ");
 MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
-
-static int __init omap_usbhs_drvinit(void)
-{
-   return platform_driver_probe(_omap_driver, usbhs_omap_probe);
-}
-
-/*
- * init before ehci and ohci drivers;
- * The usbhs core driver should be initialized much before
- * the omap ehci and ohci probe functions are called.
- * This usbhs core driver should be initialized after
- * usb tll driver
- */
-fs_initcall_sync(omap_usbhs_drvinit);
-
-static void __exit omap_usbhs_drvexit(void)
-{
-   platform_driver_unregister(_omap_driver);
-}
-module_exit(omap_usbhs_drvexit);
-- 
Regards,

Laurent Pinchart



[PATCH 0/3] Fix OMAP EHCI probe & assorted cleanups

2018-09-11 Thread Laurent Pinchart
Hello,

This series fixes a v4.19-rc1 regression that results in OMAP EHCI failing to
probe (patch 1/3) and then moves on to cleaning up related code (patches 2/3
and 3/3).

The first patch is a regression fix and should thus be merged before v4.19.
The other two patches can wait until v4.20.

Tony, as patch 1/3 fixes a problem introduced by one of your DT changes, could
you please review it ? Out of curiosity, is ethernet on the Pandaboard not
part of your regression tests ?

Lee, could you then please make sure the patch gets to mainline before v4.19
final ?

Laurent Pinchart (3):
  mfd: omap-usb-host: Use regular platform device probe mechanism
  ARM: OMAP2+: Remove legacy USB initialization code
  mfd: omap-usb-host: Drop support for non-DT probe

 arch/arm/mach-omap2/common.h|   2 -
 arch/arm/mach-omap2/omap_phy_internal.c |  96 +-
 arch/arm/mach-omap2/usb.h   |  71 -
 drivers/mfd/omap-usb-host.c | 175 +++-
 include/linux/platform_data/usb-omap.h  |   4 -
 5 files changed, 18 insertions(+), 330 deletions(-)
 delete mode 100644 arch/arm/mach-omap2/usb.h

-- 
Regards,

Laurent Pinchart



Re: [PATCH 3/4] usb: dwc3: trace: log ep commands in hex

2018-08-23 Thread Laurent Pinchart
Hi Andy,

On Thursday, 23 August 2018 12:57:57 EEST Andy Shevchenko wrote:
> On Mon, Aug 20, 2018 at 3:21 PM Laurent Pinchart wrote:
> > On Monday, 20 August 2018 15:06:31 EEST Andy Shevchenko wrote:
> >> On Mon, Aug 20, 2018 at 2:25 PM, Laurent Pinchart wrote:
> >>>> - TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status:
> >>>> %s",
> >>>> + TP_printk("%s: cmd '%s' [%x] params %08x %08x %08x --> status:
> >>>> %s",
> >>> 
> >>> How about 0x%x ?
> >> 
> >> Side note: # is one character less for the same.
> > 
> > Doesn't that print 0 instead of 0x0 ? There's no ambiguity with 0, but I
> > find that always printing the 0x is more consistent. I'll leave that up
> > to Felipe, I'm OK with both options.
> 
>#  The value should be converted to an "alternate form".
> For o conversions, the first character  of
>  the  output  string is made zero (by prefixing a 0 if it
> was not zero already).  For x and X conā€
>  versions, a nonzero result has the string "0x" (or "0X"
> for X conversions) prepended to it.

That's exactly my point, it will only prepend 0x when the value is not zero. 
Small inconsistency, but I don't mind too much.

-- 
Regards,

Laurent Pinchart





Re: [PATCH 3/4] usb: dwc3: trace: log ep commands in hex

2018-08-20 Thread Laurent Pinchart
Hi Andy,

On Monday, 20 August 2018 15:06:31 EEST Andy Shevchenko wrote:
> On Mon, Aug 20, 2018 at 2:25 PM, Laurent Pinchart wrote:
> >> - TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
> >> + TP_printk("%s: cmd '%s' [%x] params %08x %08x %08x --> status: %s",
> > 
> > How about 0x%x ?
> 
> Side note: # is one character less for the same.

Doesn't that print 0 instead of 0x0 ? There's no ambiguity with 0, but I find 
that always printing the 0x is more consistent. I'll leave that up to Felipe, 
I'm OK with both options.

-- 
Regards,

Laurent Pinchart





Re: [PATCH 2/4] usb: dwc3: gadget: check if dep->frame_number is still valid

2018-08-20 Thread Laurent Pinchart
Hi Felipe,

(CC'ing Kieran)

Thank you for the patch.

On Monday, 20 August 2018 13:29:59 EEST Felipe Balbi wrote:
> Gadget driver may take an unbounded amount of time to queue requests
> after XferNotReady. This is important for isochronous endpoints which
> need to be started for a specific (micro-)frame.
> 
> Before kicking the transfer, let's check if current frame number is
> still less than our aligned frame number that we got from the
> previous XferNotReady. If it isn't, then we'll increment
> dep->frame_number to make sure it's ahead of current frame number.
> 
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/usb/dwc3/core.h   |  2 ++
>  drivers/usb/dwc3/gadget.c | 11 +++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 285ce0ef3b91..3acf8788a680 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -685,6 +685,8 @@ struct dwc3_ep {
>   u8  type;
>   u8  resource_index;
>   u32 frame_number;
> +#define DWC3_EP_FRAME_NUMBER_MASK 0x3fff
> +
>   u32 interval;
> 
>   charname[20];
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index f61a4250c883..0bac9b02f28b 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -1257,6 +1257,9 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
> 
>  static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
>  {
> + u16 current_frame_number;
> + u16 frame_number;
> +
>   if (list_empty(>pending_list)) {
>   dev_info(dep->dwc->dev, "%s: ran out of requests\n",
>   dep->name);
> @@ -1265,6 +1268,14 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep
> *dep) }
> 
>   dep->frame_number = DWC3_ALIGN_FRAME(dep);
> + current_frame_number = __dwc3_gadget_get_frame(dep->dwc);
> + frame_number = dep->frame_number & DWC3_EP_FRAME_NUMBER_MASK;
> +
> + if (frame_number <= current_frame_number) {
> + dep->frame_number += current_frame_number - frame_number;
> + dep->frame_number = DWC3_ALIGN_FRAME(dep);
> + }
> +

This greatly improves the situation with the UVC function driver. However, 
we're still receiving errors from time to time related to missed transfer 
intervals, and those errors tend to occur in bursts. Kieran should be able to 
provide you with more information. Before acking this patch I would thus like 
to make sure that we're not missing part of the problem.

>   return __dwc3_gadget_kick_transfer(dep);
>  }

-- 
Regards,

Laurent Pinchart





Re: [PATCH 4/4] usb: dwc3: gadget: remove unnecessary dev_info()

2018-08-20 Thread Laurent Pinchart
Hi Felipe,

Thank you for the patch.

On Monday, 20 August 2018 13:30:01 EEST Felipe Balbi wrote:
> Running out of requests on isochronous endpoints is part of normal
> operation. We don't really need to know about it every time it
> happens.
> 
> Signed-off-by: Felipe Balbi 

Reviewed-by: Laurent Pinchart 

> ---
>  drivers/usb/dwc3/gadget.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 0bac9b02f28b..8d3e0f2cde8b 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -1261,8 +1261,6 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep
> *dep) u16 frame_number;
> 
>   if (list_empty(>pending_list)) {
> - dev_info(dep->dwc->dev, "%s: ran out of requests\n",
> - dep->name);
>   dep->flags |= DWC3_EP_PENDING_REQUEST;
>   return -EAGAIN;
>   }

-- 
Regards,

Laurent Pinchart





Re: [PATCH 3/4] usb: dwc3: trace: log ep commands in hex

2018-08-20 Thread Laurent Pinchart
Hi Felipe,

Thank you for the patch.

On Monday, 20 August 2018 13:30:00 EEST Felipe Balbi wrote:
> They are much more useful in hexadecimal than in decimal. Moreover,
> generic commands are already logged in hex.
> 
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/usb/dwc3/trace.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h
> index f22714cce070..50fb6f2d92dd 100644
> --- a/drivers/usb/dwc3/trace.h
> +++ b/drivers/usb/dwc3/trace.h
> @@ -199,7 +199,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
>   __entry->param2 = params->param2;
>   __entry->cmd_status = cmd_status;
>   ),
> - TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
> + TP_printk("%s: cmd '%s' [%x] params %08x %08x %08x --> status: %s",

How about 0x%x ? Otherwise one could get confused when the command 
representation in hex doesn't contain a letter (especially given that this 
patch transitions from decimal to hexadecimal).

>   __get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
>   __entry->cmd, __entry->param0,
>   __entry->param1, __entry->param2,

-- 
Regards,

Laurent Pinchart





Re: [PATCH 1/4] usb: dwc3: gadget: return errors from __dwc3_gadget_start_isoc()

2018-08-20 Thread Laurent Pinchart
Hi Felipe,

Thank you for the patch.

On Monday, 20 August 2018 13:29:58 EEST Felipe Balbi wrote:
> Sometimes, errors happen when kicking transfers from
> __dwc3_gadget_start_isoc(). In those cases, we need to pass along the
> error so gadget driver can make informed decisions.
> 
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/usb/dwc3/gadget.c | 11 +--
>  1 file changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 69bf137aab37..f61a4250c883 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -1255,17 +1255,17 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
> return DWC3_DSTS_SOFFN(reg);
>  }
> 
> -static void __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
> +static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
>  {
>   if (list_empty(>pending_list)) {
>   dev_info(dep->dwc->dev, "%s: ran out of requests\n",
>   dep->name);
>   dep->flags |= DWC3_EP_PENDING_REQUEST;
> - return;
> + return -EAGAIN;
>   }
> 
>   dep->frame_number = DWC3_ALIGN_FRAME(dep);
> - __dwc3_gadget_kick_transfer(dep);
> + return __dwc3_gadget_kick_transfer(dep);
>  }
> 
>  static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request
> *req) @@ -1306,8 +1306,7 @@ static int __dwc3_gadget_ep_queue(struct
> dwc3_ep *dep, struct dwc3_request *req)
> 
>   if ((dep->flags & DWC3_EP_PENDING_REQUEST)) {
>   if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) {
> - __dwc3_gadget_start_isoc(dep);
> - return 0;
> + return __dwc3_gadget_start_isoc(dep);

Do I understandand correctly that the new -EAGAIN error returned above when an 
underrun has occurred will never be returned here, as we call 
__dwc3_gadget_start_isoc() after adding a request to the pending_list, covered 
by the same spinlock that is taken by the IRQ handler to remove requests from 
the list ? I don't think that's an issue, but I want to make sure nothing is 
overlooked.

>   }
>   }
>   }
> @@ -2427,7 +2426,7 @@ static void
> dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, const struct
> dwc3_event_depevt *event)
>  {
>   dwc3_gadget_endpoint_frame_from_event(dep, event);
> -     __dwc3_gadget_start_isoc(dep);
> + (void) __dwc3_gadget_start_isoc(dep);

No need for a cast here.

>  }
> 
>  static void dwc3_endpoint_interrupt(struct dwc3 *dwc,

-- 
Regards,

Laurent Pinchart





[PATCH v2 2/8] usb: gadget: uvc: configfs: Add section header comments

2018-08-01 Thread Laurent Pinchart
The UVC configfs implementation is large and difficult to navigate. Add
a bit more air to the code to make it easier to read.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Kieran Bingham 
---
 drivers/usb/gadget/function/uvc_configfs.c | 120 ++---
 1 file changed, 91 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 1df94b25abe1..dbc95c9558de 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -12,6 +12,10 @@
 #include "u_uvc.h"
 #include "uvc_configfs.h"
 
+/* 
-
+ * Global Utility Structures and Macros
+ */
+
 #define UVCG_STREAMING_CONTROL_SIZE1
 
 #define UVC_ATTR(prefix, cname, aname) \
@@ -37,7 +41,11 @@ static inline struct f_uvc_opts *to_f_uvc_opts(struct 
config_item *item)
func_inst.group);
 }
 
-/* control/header/ */
+/* 
-
+ * control/header/
+ * control/header
+ */
+
 DECLARE_UVC_HEADER_DESCRIPTOR(1);
 
 struct uvcg_control_header {
@@ -161,7 +169,6 @@ static void uvcg_control_header_drop(struct config_group 
*group,
kfree(h);
 }
 
-/* control/header */
 static struct config_group uvcg_control_header_grp;
 
 static struct configfs_group_operations uvcg_control_header_grp_ops = {
@@ -174,7 +181,10 @@ static const struct config_item_type 
uvcg_control_header_grp_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* control/processing/default */
+/* 
-
+ * control/processing/default
+ */
+
 static struct config_group uvcg_default_processing_grp;
 
 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv)   \
@@ -260,16 +270,20 @@ static const struct config_item_type 
uvcg_default_processing_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* struct uvcg_processing {}; */
+/* 
-
+ * control/processing
+ */
 
-/* control/processing */
 static struct config_group uvcg_processing_grp;
 
 static const struct config_item_type uvcg_processing_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control/terminal/camera/default */
+/* 
-
+ * control/terminal/camera/default
+ */
+
 static struct config_group uvcg_default_camera_grp;
 
 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv)   \
@@ -366,16 +380,20 @@ static const struct config_item_type 
uvcg_default_camera_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* struct uvcg_camera {}; */
+/* 
-
+ * control/terminal/camera
+ */
 
-/* control/terminal/camera */
 static struct config_group uvcg_camera_grp;
 
 static const struct config_item_type uvcg_camera_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control/terminal/output/default */
+/* 
-
+ * control/terminal/output/default
+ */
+
 static struct config_group uvcg_default_output_grp;
 
 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv)   \
@@ -433,23 +451,30 @@ static const struct config_item_type 
uvcg_default_output_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* struct uvcg_output {}; */
+/* 
-
+ * control/terminal/output
+ */
 
-/* control/terminal/output */
 static struct config_group uvcg_output_grp;
 
 static const struct config_item_type uvcg_output_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control/terminal */
+/* 
-
+ * control/terminal
+ */
+
 static struct config_group uvcg_terminal_grp;
 
 static const struct config_item_type uvcg_terminal_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control/class/{fs} */
+/* 
-
+ * control/class/{fs|ss}
+ */
+
 static struct config_group uvcg_control_class_fs_grp;
 static struct config_group uvcg_control_class_ss_grp;
 
@@ -552,24 +577,32 @@ static const struct config_item_type 
uvcg_control_class_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* control/class */
+/* 
-
+ * control/class
+ */
+
 static struct config_group uvcg_control_class_grp;
 
 static const struct config_item_type uvcg_control_class_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control */
+/* 
-
+ * control
+ */
+
 static

[PATCH v2 8/8] usb: gadget: uvc: configfs: Prevent format changes after linking header

2018-08-01 Thread Laurent Pinchart
From: Joel Pepper 

While checks are in place to avoid attributes and children of a format
being manipulated after the format is linked into the streaming header,
the linked flag was never actually set, invalidating the protections.

Signed-off-by: Joel Pepper 
---
 drivers/usb/gadget/function/uvc_configfs.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index b8763343dcae..799dc32c5bc7 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -928,6 +928,7 @@ static int uvcg_streaming_header_allow_link(struct 
config_item *src,
format_ptr->fmt = target_fmt;
list_add_tail(_ptr->entry, _hdr->formats);
++src_hdr->num_fmt;
+   ++target_fmt->linked;
 
 out:
mutex_unlock(>lock);
@@ -965,6 +966,8 @@ static void uvcg_streaming_header_drop_link(struct 
config_item *src,
break;
}
 
+   --target_fmt->linked;
+
 out:
mutex_unlock(>lock);
mutex_unlock(su_mutex);
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 0/8] usb: gadget: uvc: Improve configfs support

2018-08-01 Thread Laurent Pinchart
Hello,

This patch series reworks the UVC gadget function configfs implementation to
support multiple UVC functions in a single device and 

The first two patches simplify the code (01/08) and improve readability
(02/08).

The series then moves to dynamically allocating all configfs groups to support
multiple instances. It first fixes a config item reference leak (03/08) that
would cause a memory leak with dynamic allocation, and then allocate configfs
groups dynamically (04/08).

As a consequence we have to expose the interface numbers through new configfs
attributes (05/08) in order to let the userspace helper application discover
them. The next two patches add and document new bFormatIndex (06/08) and
bFrameIndex (07/08) configfs attributes to expose indices of UVC format and
frame descriptors to userspace, allowing their dynamic discovery.

The last patch finally fixes a bug that allowed modification of descriptors
after linking them (08/08).

Felipe, all this is based on top of your testing/next branch, and is a
candidate for v4.20. Please let me know if I should base the patches on a
different branch.

Changes since v1:

- Fix config items reference leak
- Free dynamically allocated configfs groups
- Squash attribute documentation and attribute creation patches

Joel Pepper (2):
  usb: gadget: uvc: configfs: Add bFrameIndex attributes
  usb: gadget: uvc: configfs: Prevent format changes after linking
header

Laurent Pinchart (6):
  usb: gadget: uvc: configfs: Don't wrap groups unnecessarily
  usb: gadget: uvc: configfs: Add section header comments
  usb: gadget: uvc: configfs: Drop leaked references to config items
  usb: gadget: uvc: configfs: Allocate groups dynamically
  usb: gadget: uvc: configfs: Add interface number attributes
  usb: gadget: uvc: configfs: Add bFormatIndex attributes

 Documentation/ABI/testing/configfs-usb-gadget-uvc |  24 +
 drivers/usb/gadget/function/f_uvc.c   |  10 +-
 drivers/usb/gadget/function/u_uvc.h   |   3 +
 drivers/usb/gadget/function/uvc_configfs.c| 926 +-
 4 files changed, 600 insertions(+), 363 deletions(-)

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 5/8] usb: gadget: uvc: configfs: Add interface number attributes

2018-08-01 Thread Laurent Pinchart
The video control and video streaming interface numbers are needed in
the UVC gadget userspace stack to reply to UVC requests. They are
hardcoded to fixed values at the moment, preventing configurations with
multiple functions.

To fix this, make them dynamically discoverable by userspace through
read-only configfs attributes in /control/bInterfaceNumber and
/streaming/bInterfaceNumber respectively.

Signed-off-by: Laurent Pinchart 
---
Changes since v1:

- Document the new attribute
---
 Documentation/ABI/testing/configfs-usb-gadget-uvc |  8 +++
 drivers/usb/gadget/function/f_uvc.c   |  2 +
 drivers/usb/gadget/function/u_uvc.h   |  3 ++
 drivers/usb/gadget/function/uvc_configfs.c| 62 +++
 4 files changed, 75 insertions(+)

diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc 
b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 9281e2aa38df..490a0136fb02 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -12,6 +12,10 @@ Date:Dec 2014
 KernelVersion: 4.0
 Description:   Control descriptors
 
+   All attributes read only:
+   bInterfaceNumber- USB interface number for this
+ streaming interface
+
 What:  /config/usb-gadget/gadget/functions/uvc.name/control/class
 Date:  Dec 2014
 KernelVersion: 4.0
@@ -109,6 +113,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Streaming descriptors
 
+   All attributes read only:
+   bInterfaceNumber- USB interface number for this
+ streaming interface
+
 What:  /config/usb-gadget/gadget/functions/uvc.name/streaming/class
 Date:  Dec 2014
 KernelVersion: 4.0
diff --git a/drivers/usb/gadget/function/f_uvc.c 
b/drivers/usb/gadget/function/f_uvc.c
index 95cb1b5f5ffe..4ea987741e6e 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -699,12 +699,14 @@ uvc_function_bind(struct usb_configuration *c, struct 
usb_function *f)
uvc_iad.bFirstInterface = ret;
uvc_control_intf.bInterfaceNumber = ret;
uvc->control_intf = ret;
+   opts->control_interface = ret;
 
if ((ret = usb_interface_id(c, f)) < 0)
goto error;
uvc_streaming_intf_alt0.bInterfaceNumber = ret;
uvc_streaming_intf_alt1.bInterfaceNumber = ret;
uvc->streaming_intf = ret;
+   opts->streaming_interface = ret;
 
/* Copy descriptors */
f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
diff --git a/drivers/usb/gadget/function/u_uvc.h 
b/drivers/usb/gadget/function/u_uvc.h
index 2ed292e94fbc..5242d489e20a 100644
--- a/drivers/usb/gadget/function/u_uvc.h
+++ b/drivers/usb/gadget/function/u_uvc.h
@@ -25,6 +25,9 @@ struct f_uvc_opts {
unsigned intstreaming_maxpacket;
unsigned intstreaming_maxburst;
 
+   unsigned intcontrol_interface;
+   unsigned intstreaming_interface;
+
/*
 * Control descriptors array pointers for full-/high-speed and
 * super-speed. They point by default to the uvc_fs_control_cls and
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index ae722549eabc..fa8d2e1f54ba 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -713,9 +713,40 @@ static const struct uvcg_config_group_type 
uvcg_control_class_grp_type = {
  * control
  */
 
+static ssize_t uvcg_default_control_b_interface_number_show(
+   struct config_item *item, char *page)
+{
+   struct config_group *group = to_config_group(item);
+   struct mutex *su_mutex = >cg_subsys->su_mutex;
+   struct config_item *opts_item;
+   struct f_uvc_opts *opts;
+   int result = 0;
+
+   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+   opts_item = item->ci_parent;
+   opts = to_f_uvc_opts(opts_item);
+
+   mutex_lock(>lock);
+   result += sprintf(page, "%u\n", opts->control_interface);
+   mutex_unlock(>lock);
+
+   mutex_unlock(su_mutex);
+
+   return result;
+}
+
+UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber);
+
+static struct configfs_attribute *uvcg_default_control_attrs[] = {
+   _default_control_attr_b_interface_number,
+   NULL,
+};
+
 static const struct uvcg_config_group_type uvcg_control_grp_type = {
.type = {
.ct_item_ops= _config_item_ops,
+   .ct_attrs   = uvcg_default_control_attrs,
.ct_owner   = THIS_MODULE,
},
.name = "c

[PATCH v2 4/8] usb: gadget: uvc: configfs: Allocate groups dynamically

2018-08-01 Thread Laurent Pinchart
The UVC configfs implementation creates all groups as global static
variables. This prevents creation of multiple UVC function instances,
as they would all require their own configfs group instances.

Fix this by allocating all groups dynamically. To avoid duplicating code
around, extend the config_item_type structure with group name and
children, and implement helper functions to create children
automatically for most groups.

Signed-off-by: Laurent Pinchart 
---
Changes since v1:

- Free groups by implementing .release() handler and removing children
  explicitly.
---
 drivers/usb/gadget/function/f_uvc.c|   8 +-
 drivers/usb/gadget/function/uvc_configfs.c | 581 -
 2 files changed, 338 insertions(+), 251 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uvc.c 
b/drivers/usb/gadget/function/f_uvc.c
index d8ce7868fe22..95cb1b5f5ffe 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -792,6 +792,7 @@ static struct usb_function_instance *uvc_alloc_inst(void)
struct uvc_output_terminal_descriptor *od;
struct uvc_color_matching_descriptor *md;
struct uvc_descriptor_header **ctl_cls;
+   int ret;
 
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
@@ -868,7 +869,12 @@ static struct usb_function_instance *uvc_alloc_inst(void)
opts->streaming_interval = 1;
opts->streaming_maxpacket = 1024;
 
-   uvcg_attach_configfs(opts);
+   ret = uvcg_attach_configfs(opts);
+   if (ret < 0) {
+   kfree(opts);
+   return ERR_PTR(ret);
+   }
+
return >func_inst;
 }
 
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 8d513cc6fb8c..ae722549eabc 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -41,6 +41,71 @@ static inline struct f_uvc_opts *to_f_uvc_opts(struct 
config_item *item)
func_inst.group);
 }
 
+struct uvcg_config_group_type {
+   struct config_item_type type;
+   const char *name;
+   const struct uvcg_config_group_type **children;
+   int (*create_children)(struct config_group *group);
+};
+
+static void uvcg_config_item_release(struct config_item *item)
+{
+   struct config_group *group = to_config_group(item);
+
+   kfree(group);
+}
+
+static struct configfs_item_operations uvcg_config_item_ops = {
+   .release= uvcg_config_item_release,
+};
+
+static int uvcg_config_create_group(struct config_group *parent,
+   const struct uvcg_config_group_type *type);
+
+static int uvcg_config_create_children(struct config_group *group,
+   const struct uvcg_config_group_type *type)
+{
+   const struct uvcg_config_group_type **child;
+   int ret;
+
+   if (type->create_children)
+   return type->create_children(group);
+
+   for (child = type->children; child && *child; ++child) {
+   ret = uvcg_config_create_group(group, *child);
+   if (ret < 0)
+   return ret;
+   }
+
+   return 0;
+}
+
+static int uvcg_config_create_group(struct config_group *parent,
+   const struct uvcg_config_group_type *type)
+{
+   struct config_group *group;
+
+   group = kzalloc(sizeof(*group), GFP_KERNEL);
+   if (!group)
+   return -ENOMEM;
+
+   config_group_init_type_name(group, type->name, >type);
+   configfs_add_default_group(group, parent);
+
+   return uvcg_config_create_children(group, type);
+}
+
+static void uvcg_config_remove_children(struct config_group *group)
+{
+   struct config_group *child, *n;
+
+   list_for_each_entry_safe(child, n, >default_groups, group_entry) 
{
+   list_del(>group_entry);
+   uvcg_config_remove_children(child);
+   config_item_put(>cg_item);
+   }
+}
+
 /* 
-
  * control/header/
  * control/header
@@ -137,6 +202,7 @@ static struct configfs_attribute 
*uvcg_control_header_attrs[] = {
 };
 
 static const struct config_item_type uvcg_control_header_type = {
+   .ct_item_ops= _config_item_ops,
.ct_attrs   = uvcg_control_header_attrs,
.ct_owner   = THIS_MODULE,
 };
@@ -161,32 +227,23 @@ static struct config_item 
*uvcg_control_header_make(struct config_group *group,
return >item;
 }
 
-static void uvcg_control_header_drop(struct config_group *group,
- struct config_item *item)
-{
-   struct uvcg_control_header *h = to_uvcg_control_header(item);
-
-   kfree(h);
-}
-
-static struct config_group uvcg_control_header_grp;
-
 static struct configfs_group_operations 

[PATCH v2 6/8] usb: gadget: uvc: configfs: Add bFormatIndex attributes

2018-08-01 Thread Laurent Pinchart
The UVC format description are numbered using the descriptor's
bFormatIndex field. The index is used in UVC requests, and is thus
needed to handle requests in userspace. Make it dynamically discoverable
by exposing it in a bFormatIndex configfs attribute of the uncompressed
and mjpeg format config items.

The bFormatIndex value exposed through the attribute is stored in the
config item private data. However, that value is never set: the driver
instead computes the bFormatIndex value when linking the stream class
header in the configfs hierarchy and stores it directly in the class
descriptors in a separate structure. In order to expose the value
through the configfs attribute, store it in the config item private data
as well. This results in a small code simplification.

Signed-off-by: Laurent Pinchart 
---

Changes since v1:

- Squash patch "usb: gadget: uvc: configfs: Document the bFormatIndex
  attribute".
---
 Documentation/ABI/testing/configfs-usb-gadget-uvc |  8 
 drivers/usb/gadget/function/uvc_configfs.c| 14 --
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc 
b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 490a0136fb02..a6cc8d6d398e 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -168,6 +168,10 @@ Description:   Specific MJPEG format descriptors
 
All attributes read only,
except bmaControls and bDefaultFrameIndex:
+   bFormatIndex- unique id for this format descriptor;
+   only defined after parent header is
+   linked into the streaming class;
+   read-only
bmaControls - this format's data for bmaControls in
the streaming header
bmInterfaceFlags- specifies interlace information,
@@ -212,6 +216,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific uncompressed format descriptors
 
+   bFormatIndex- unique id for this format descriptor;
+   only defined after parent header is
+   linked into the streaming class;
+   read-only
bmaControls - this format's data for bmaControls in
the streaming header
bmInterfaceFlags- specifies interlace information,
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index fa8d2e1f54ba..5cee8aca3734 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1538,6 +1538,7 @@ UVC_ATTR(uvcg_uncompressed_, cname, aname);
 
 #define identity_conv(x) (x)
 
+UVCG_UNCOMPRESSED_ATTR_RO(b_format_index, bFormatIndex, identity_conv);
 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, identity_conv);
 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex,
   identity_conv);
@@ -1568,6 +1569,7 @@ uvcg_uncompressed_bma_controls_store(struct config_item 
*item,
 UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
 
 static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
+   _uncompressed_attr_b_format_index,
_uncompressed_attr_guid_format,
_uncompressed_attr_b_bits_per_pixel,
_uncompressed_attr_b_default_frame_index,
@@ -1738,6 +1740,7 @@ UVC_ATTR(uvcg_mjpeg_, cname, aname)
 
 #define identity_conv(x) (x)
 
+UVCG_MJPEG_ATTR_RO(b_format_index, bFormatIndex, identity_conv);
 UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex,
   identity_conv);
 UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, identity_conv);
@@ -1768,6 +1771,7 @@ uvcg_mjpeg_bma_controls_store(struct config_item *item,
 UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
 
 static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
+   _mjpeg_attr_b_format_index,
_mjpeg_attr_b_default_frame_index,
_mjpeg_attr_bm_flags,
_mjpeg_attr_b_aspect_ratio_x,
@@ -2079,24 +2083,22 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, 
void *priv3, int n,
struct uvcg_format *fmt = priv1;
 
if (fmt->type == UVCG_UNCOMPRESSED) {
-   struct uvc_format_uncompressed *unc = *dest;
struct uvcg_uncompressed *u =
container_of(fmt, struct uvcg_uncompressed,
 fmt);
 
+   u->desc.bFormatIndex = n + 1;
+   u->desc.bNumFrameDescriptors = fmt->num_frames;
memcpy(*dest, >desc, sizeof(u->desc));
   

[PATCH v2 1/8] usb: gadget: uvc: configfs: Don't wrap groups unnecessarily

2018-08-01 Thread Laurent Pinchart
Various configfs groups (represented by config_group) are wrapped in
structures that they're the only member of. This allows adding other
data fields to groups, but it unnecessarily makes the code more complex.
Remove the outer structures and use config_group directly to simplify
the code. Groups can still be wrapped individually in the future if
other data fields need to be added.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Kieran Bingham 
---
 drivers/usb/gadget/function/uvc_configfs.c | 302 +++--
 1 file changed, 117 insertions(+), 185 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index b51f0d278826..1df94b25abe1 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -162,9 +162,7 @@ static void uvcg_control_header_drop(struct config_group 
*group,
 }
 
 /* control/header */
-static struct uvcg_control_header_grp {
-   struct config_group group;
-} uvcg_control_header_grp;
+static struct config_group uvcg_control_header_grp;
 
 static struct configfs_group_operations uvcg_control_header_grp_ops = {
.make_item  = uvcg_control_header_make,
@@ -177,31 +175,22 @@ static const struct config_item_type 
uvcg_control_header_grp_type = {
 };
 
 /* control/processing/default */
-static struct uvcg_default_processing {
-   struct config_group group;
-} uvcg_default_processing;
-
-static inline struct uvcg_default_processing
-*to_uvcg_default_processing(struct config_item *item)
-{
-   return container_of(to_config_group(item),
-   struct uvcg_default_processing, group);
-}
+static struct config_group uvcg_default_processing_grp;
 
 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv)   \
 static ssize_t uvcg_default_processing_##cname##_show( \
struct config_item *item, char *page)   \
 {  \
-   struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
+   struct config_group *group = to_config_group(item); \
struct f_uvc_opts *opts;\
struct config_item *opts_item;  \
-   struct mutex *su_mutex = >group.cg_subsys->su_mutex;\
+   struct mutex *su_mutex = >cg_subsys->su_mutex;   \
struct uvc_processing_unit_descriptor *pd;  \
int result; \
\
mutex_lock(su_mutex); /* for navigating configfs hierarchy */   \
\
-   opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;  \
+   opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item);\
pd = >uvc_processing; \
\
@@ -229,17 +218,17 @@ UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 
identity_conv);
 static ssize_t uvcg_default_processing_bm_controls_show(
struct config_item *item, char *page)
 {
-   struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
+   struct config_group *group = to_config_group(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
-   struct mutex *su_mutex = >group.cg_subsys->su_mutex;
+   struct mutex *su_mutex = >cg_subsys->su_mutex;
struct uvc_processing_unit_descriptor *pd;
int result, i;
char *pg = page;
 
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
 
-   opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;
+   opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
pd = >uvc_processing;
 
@@ -274,40 +263,29 @@ static const struct config_item_type 
uvcg_default_processing_type = {
 /* struct uvcg_processing {}; */
 
 /* control/processing */
-static struct uvcg_processing_grp {
-   struct config_group group;
-} uvcg_processing_grp;
+static struct config_group uvcg_processing_grp;
 
 static const struct config_item_type uvcg_processing_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
 /* control/terminal/camera/default */
-static struct uvcg_default_camera {
-   struct config_group group;
-} uvcg_default_camera;
-
-static inline struct uvcg_default_camera
-*to_uvcg_default_camera(struct config_item *item)
-{
-   return container_of(to_config_group(item),
-   struct uvcg_default_camera, group);

[PATCH v2 3/8] usb: gadget: uvc: configfs: Drop leaked references to config items

2018-08-01 Thread Laurent Pinchart
Some of the .allow_link() and .drop_link() operations implementations
call config_group_find_item() and then leak the reference to the
returned item. Fix this by dropping those references where needed.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_configfs.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index dbc95c9558de..8d513cc6fb8c 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -529,6 +529,7 @@ static int uvcg_control_class_allow_link(struct config_item 
*src,
 unlock:
mutex_unlock(>lock);
 out:
+   config_item_put(header);
mutex_unlock(su_mutex);
return ret;
 }
@@ -564,6 +565,7 @@ static void uvcg_control_class_drop_link(struct config_item 
*src,
 unlock:
mutex_unlock(>lock);
 out:
+   config_item_put(header);
mutex_unlock(su_mutex);
 }
 
@@ -2026,6 +2028,7 @@ static int uvcg_streaming_class_allow_link(struct 
config_item *src,
 unlock:
mutex_unlock(>lock);
 out:
+   config_item_put(header);
mutex_unlock(su_mutex);
return ret;
 }
@@ -2066,6 +2069,7 @@ static void uvcg_streaming_class_drop_link(struct 
config_item *src,
 unlock:
mutex_unlock(>lock);
 out:
+   config_item_put(header);
mutex_unlock(su_mutex);
 }
 
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 7/8] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-08-01 Thread Laurent Pinchart
From: Joel Pepper 

- Add bFrameIndex as a UVCG_FRAME_ATTR_RO for each frame size.
- Automatically assign ascending bFrameIndex to each frame in a format.

Before all "bFrameindex" attributes were set to "1" with no way to
configure the gadget otherwise. This resulted in the host always
negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
After the negotiation the host driver will set the user or application
selected framesize, while the gadget is actually set to the first
framesize.

Now, when the containing format is linked into the streaming header,
iterate over all child frame descriptors and assign ascending indices.
The automatically assigned indices can be read from the new read only
bFrameIndex configsfs attribute in each frame descriptor item.

Signed-off-by: Joel Pepper 
[Simplified documentation, renamed function, blank space update]
Signed-off-by: Laurent Pinchart 
---
 Documentation/ABI/testing/configfs-usb-gadget-uvc |  8 
 drivers/usb/gadget/function/uvc_configfs.c| 56 +++
 2 files changed, 64 insertions(+)

diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc 
b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index a6cc8d6d398e..809765bd9573 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -189,6 +189,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific MJPEG frame descriptors
 
+   bFrameIndex - unique id for this framedescriptor;
+   only defined after parent format is
+   linked into the streaming header;
+   read-only
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
@@ -240,6 +244,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific uncompressed frame descriptors
 
+   bFrameIndex - unique id for this framedescriptor;
+   only defined after parent format is
+   linked into the streaming header;
+   read-only
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 5cee8aca3734..b8763343dcae 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -868,6 +868,8 @@ static struct uvcg_streaming_header 
*to_uvcg_streaming_header(struct config_item
return container_of(item, struct uvcg_streaming_header, item);
 }
 
+static void uvcg_format_set_indices(struct config_group *fmt);
+
 static int uvcg_streaming_header_allow_link(struct config_item *src,
struct config_item *target)
 {
@@ -915,6 +917,8 @@ static int uvcg_streaming_header_allow_link(struct 
config_item *src,
if (!target_fmt)
goto out;
 
+   uvcg_format_set_indices(to_config_group(target));
+
format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
if (!format_ptr) {
ret = -ENOMEM;
@@ -1146,6 +1150,41 @@ end: 
\
\
 UVC_ATTR(uvcg_frame_, cname, aname);
 
+static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
+char *page)
+{
+   struct uvcg_frame *f = to_uvcg_frame(item);
+   struct uvcg_format *fmt;
+   struct f_uvc_opts *opts;
+   struct config_item *opts_item;
+   struct config_item *fmt_item;
+   struct mutex *su_mutex = >item.ci_group->cg_subsys->su_mutex;
+   int result;
+
+   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+   fmt_item = f->item.ci_parent;
+   fmt = to_uvcg_format(fmt_item);
+
+   if (!fmt->linked) {
+   result = -EBUSY;
+   goto out;
+   }
+
+   opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
+   opts = to_f_uvc_opts(opts_item);
+
+   mutex_lock(>lock);
+   result = sprintf(page, "%d\n", f->frame.b_frame_index);
+   mutex_unlock(>lock);
+
+out:
+   mutex_unlock(su_mutex);
+   return result;
+}
+
+UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
+
 #define noop_conversion(x) (x)
 
 UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
@@ -1294,6 +1333,7 @@ static

Re: [PATCH 4/8] usb: gadget: uvc: configfs: Add interface number attributes

2018-08-01 Thread Laurent Pinchart
Hi Kieran,

On Wednesday, 1 August 2018 13:07:20 EEST Kieran Bingham wrote:
> On 01/08/18 01:29, Laurent Pinchart wrote:
> > The video control and video streaming interface numbers are needed in
> > the UVC gadget userspace stack to reply to UVC requests. They are
> > hardcoded to fixed values at the moment, preventing configurations with
> > multiple functions.
> > 
> > To fix this, make them dynamically discoverable by userspace through
> > read-only configfs attributes in /control/bInterfaceNumber and
> > /streaming/bInterfaceNumber respectively.
> > 
> > Signed-off-by: Laurent Pinchart 
> > ---
> > 
> >  drivers/usb/gadget/function/f_uvc.c|  2 +
> >  drivers/usb/gadget/function/u_uvc.h|  3 ++
> >  drivers/usb/gadget/function/uvc_configfs.c | 62 +
> It sounds like this is extending the userspace ABI.
> 
> Do we need to document this anywhere?
>  Documentation/ABI/testing/configfs-usb-gadget-uvc ?

You're right, I'll document it.

> >  3 files changed, 67 insertions(+)

[snip]

> > diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> > b/drivers/usb/gadget/function/uvc_configfs.c index
> > e019ea317c7a..801117686108 100644
> > --- a/drivers/usb/gadget/function/uvc_configfs.c
> > +++ b/drivers/usb/gadget/function/uvc_configfs.c
> > @@ -687,8 +687,39 @@ static const struct uvcg_config_group_type
> > uvcg_control_class_grp_type = {> 
> >   * control
> >   */
> > 
> > +static ssize_t uvcg_default_control_b_interface_number_show(
> > +   struct config_item *item, char *page)
> > +{
> > +   struct config_group *group = to_config_group(item);
> > +   struct mutex *su_mutex = >cg_subsys->su_mutex;
> > +   struct config_item *opts_item;
> > +   struct f_uvc_opts *opts;
> > +   int result = 0;
> > +
> > +   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
> > +
> > +   opts_item = item->ci_parent;
> > +   opts = to_f_uvc_opts(opts_item);
> > +
> > +   mutex_lock(>lock);
> > +   result += sprintf(page, "%u\n", opts->control_interface);
> > +   mutex_unlock(>lock);
> > +
> > +   mutex_unlock(su_mutex);
> > +
> > +   return result;
> > +}
> > +
> > +UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber);
> > +
> > +static struct configfs_attribute *uvcg_default_control_attrs[] = {
> > +   _default_control_attr_b_interface_number,
> > +   NULL,
> > +};

[snip]

> > +static ssize_t uvcg_default_streaming_b_interface_number_show(
> > +   struct config_item *item, char *page)
> > +{
> > +   struct config_group *group = to_config_group(item);
> > +   struct mutex *su_mutex = >cg_subsys->su_mutex;
> > +   struct config_item *opts_item;
> > +   struct f_uvc_opts *opts;
> > +   int result = 0;
> > +
> > +   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
> > +
> > +   opts_item = item->ci_parent;
> > +   opts = to_f_uvc_opts(opts_item);
> > +
> > +   mutex_lock(>lock);
> > +   result += sprintf(page, "%u\n", opts->streaming_interface);
> > +   mutex_unlock(>lock);
> > +
> > +   mutex_unlock(su_mutex);
> > +
> > +   return result;
> > +}
> 
> That looks like a lot of common boilerplate code copied for each file
> which prints a single %u.
> 
> Perhaps we should convert those to a macro - but for now they look fine.

Feel free to submit patches :-) Helper functions would be event better than 
macros to decrease the object size.

> > +
> > +UVC_ATTR_RO(uvcg_default_streaming_, b_interface_number,
> > bInterfaceNumber);
> > +static struct configfs_attribute
> > *uvcg_default_streaming_attrs[] = {
> > +   _default_streaming_attr_b_interface_number,
> > +   NULL,
> > +};

[snip]

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/8] usb: gadget: uvc: configfs: Allocate groups dynamically

2018-08-01 Thread Laurent Pinchart
Hi Kieran,

On Wednesday, 1 August 2018 12:58:40 EEST Kieran Bingham wrote:
> On 01/08/18 01:29, Laurent Pinchart wrote:
> > The UVC configfs implementation creates all groups as global static
> > variables. This prevents creationg of multiple UVC function instances,
> 
> /creationg/creation/
> 
> > as they would all require their own configfs group instances.
> > 
> > Fix this by allocating all groups dynamically. To avoid duplicating code
> > around, extend the config_item_type structure with group name and
> > children, and implement helper functions to create children
> > automatically for most groups.
> > 
> > Signed-off-by: Laurent Pinchart 
> 
> I'm struggling to see what paths free all of the dynamically created
> children in this patch.
> 
> Is this already supported by the config_group framework?
> 
> I see a reference to config_group_put(>func_inst.group); in one
> error path - but that's about it.
> 
> Am I missing something nice and obvious? (or is it already handled by
> framework code not in this patch)
> 
> 
> In fact, I can't see how it could be handled by core - as the children
> are added to a new structure you have created.
> 
> I'll let you look into this :)

I did, for a whole day :-S It wasn't easy as the configfs documentation is 
quite terse, and doesn't clearly explain when and how references should be 
acquired and released. I'll post a v2 shortly.

> > ---
> > 
> >  drivers/usb/gadget/function/f_uvc.c|   8 +-
> >  drivers/usb/gadget/function/uvc_configfs.c | 480 ++--
> >  2 files changed, 282 insertions(+), 206 deletions(-)

[snip]


> > diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> > b/drivers/usb/gadget/function/uvc_configfs.c index
> > dbc95c9558de..e019ea317c7a 100644
> > --- a/drivers/usb/gadget/function/uvc_configfs.c
> > +++ b/drivers/usb/gadget/function/uvc_configfs.c

[snip]

> > -static struct config_group uvcg_terminal_grp;
> > -
> > -static const struct config_item_type uvcg_terminal_grp_type = {
> > -   .ct_owner = THIS_MODULE,
> > +static const struct uvcg_config_group_type uvcg_terminal_grp_type = {
> > +   .type = {
> > +   .ct_owner = THIS_MODULE,
> > +   },
> > +   .name = "terminal",
> > +   .children = (const struct uvcg_config_group_type*[]) {
> 
> Is this cast really needed? Or is it just to constify the array ?

It's needed to make the expression within the curly braces an array that is 
then turned into a pointer to initialize the children field, which is defined 
as

const struct uvcg_config_group_type **children;

Without that you would get the following compilation errors.

drivers/usb/gadget/function/uvc_configfs.c:557:2: error: braces around scalar 
initializer [-Werror]
drivers/usb/gadget/function/uvc_configfs.c:557:2: error: (near initialization 
for ā€˜uvcg_terminal_grp_type.childrenā€™) [-Werror]
drivers/usb/gadget/function/uvc_configfs.c:558:3: error: initialization from 
incompatible pointer type [-Werror] 
drivers/usb/gadget/function/uvc_configfs.c:558:3: error: (near initialization 
for ā€˜uvcg_terminal_grp_type.childrenā€™) [-Werror]
drivers/usb/gadget/function/uvc_configfs.c:559:3: error: excess elements in 
scalar initializer [-Werror] 
drivers/usb/gadget/function/uvc_configfs.c:559:3: error: (near initialization 
for ā€˜uvcg_terminal_grp_type.childrenā€™) [-Werror]
drivers/usb/gadget/function/uvc_configfs.c:560:3: error: excess elements in 
scalar initializer [-Werror] 
drivers/usb/gadget/function/uvc_configfs.c:560:3: error: (near initialization 
for ā€˜uvcg_terminal_grp_type.childrenā€™) [-Werror]

Such a syntax removes the need to declare the array externally to 
uvcg_terminal_grp_type as

static const struct uvcg_config_group_type *uvcg_terminal_grp_children[] = {
_camera_grp_type,
_output_grp_type,
NULL,
};

static const struct uvcg_config_group_type uvcg_terminal_grp_type = {
.type = {
        .ct_owner = THIS_MODULE,
},
.name = "terminal",
.children = uvcg_terminal_grp_children,
};

> > +   _camera_grp_type,
> > +   _output_grp_type,
> > +   NULL,
> > +   },
> >  };

[snip]

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/8] usb: gadget: uvc: configfs: Prevent format changes after linking header

2018-07-31 Thread Laurent Pinchart
From: Joel Pepper 

While checks are in place to avoid attributes and children of a format
being manipulated after the format is linked into the streaming header,
the linked flag was never actually set, invalidating the protections.

Signed-off-by: Joel Pepper 
---
 drivers/usb/gadget/function/uvc_configfs.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 9af4cda27865..cac249e8a7ec 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -901,6 +901,7 @@ static int uvcg_streaming_header_allow_link(struct 
config_item *src,
format_ptr->fmt = target_fmt;
list_add_tail(_ptr->entry, _hdr->formats);
++src_hdr->num_fmt;
+   ++target_fmt->linked;
 
 out:
mutex_unlock(>lock);
@@ -938,6 +939,8 @@ static void uvcg_streaming_header_drop_link(struct 
config_item *src,
break;
}
 
+   --target_fmt->linked;
+
 out:
mutex_unlock(>lock);
mutex_unlock(su_mutex);
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/8] usb: gadget: uvc: configfs: Add interface number attributes

2018-07-31 Thread Laurent Pinchart
The video control and video streaming interface numbers are needed in
the UVC gadget userspace stack to reply to UVC requests. They are
hardcoded to fixed values at the moment, preventing configurations with
multiple functions.

To fix this, make them dynamically discoverable by userspace through
read-only configfs attributes in /control/bInterfaceNumber and
/streaming/bInterfaceNumber respectively.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/f_uvc.c|  2 +
 drivers/usb/gadget/function/u_uvc.h|  3 ++
 drivers/usb/gadget/function/uvc_configfs.c | 62 ++
 3 files changed, 67 insertions(+)

diff --git a/drivers/usb/gadget/function/f_uvc.c 
b/drivers/usb/gadget/function/f_uvc.c
index 95cb1b5f5ffe..4ea987741e6e 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -699,12 +699,14 @@ uvc_function_bind(struct usb_configuration *c, struct 
usb_function *f)
uvc_iad.bFirstInterface = ret;
uvc_control_intf.bInterfaceNumber = ret;
uvc->control_intf = ret;
+   opts->control_interface = ret;
 
if ((ret = usb_interface_id(c, f)) < 0)
goto error;
uvc_streaming_intf_alt0.bInterfaceNumber = ret;
uvc_streaming_intf_alt1.bInterfaceNumber = ret;
uvc->streaming_intf = ret;
+   opts->streaming_interface = ret;
 
/* Copy descriptors */
f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
diff --git a/drivers/usb/gadget/function/u_uvc.h 
b/drivers/usb/gadget/function/u_uvc.h
index 2ed292e94fbc..5242d489e20a 100644
--- a/drivers/usb/gadget/function/u_uvc.h
+++ b/drivers/usb/gadget/function/u_uvc.h
@@ -25,6 +25,9 @@ struct f_uvc_opts {
unsigned intstreaming_maxpacket;
unsigned intstreaming_maxburst;
 
+   unsigned intcontrol_interface;
+   unsigned intstreaming_interface;
+
/*
 * Control descriptors array pointers for full-/high-speed and
 * super-speed. They point by default to the uvc_fs_control_cls and
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index e019ea317c7a..801117686108 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -687,8 +687,39 @@ static const struct uvcg_config_group_type 
uvcg_control_class_grp_type = {
  * control
  */
 
+static ssize_t uvcg_default_control_b_interface_number_show(
+   struct config_item *item, char *page)
+{
+   struct config_group *group = to_config_group(item);
+   struct mutex *su_mutex = >cg_subsys->su_mutex;
+   struct config_item *opts_item;
+   struct f_uvc_opts *opts;
+   int result = 0;
+
+   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+   opts_item = item->ci_parent;
+   opts = to_f_uvc_opts(opts_item);
+
+   mutex_lock(>lock);
+   result += sprintf(page, "%u\n", opts->control_interface);
+   mutex_unlock(>lock);
+
+   mutex_unlock(su_mutex);
+
+   return result;
+}
+
+UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber);
+
+static struct configfs_attribute *uvcg_default_control_attrs[] = {
+   _default_control_attr_b_interface_number,
+   NULL,
+};
+
 static const struct uvcg_config_group_type uvcg_control_grp_type = {
.type = {
+   .ct_attrs = uvcg_default_control_attrs,
.ct_owner = THIS_MODULE,
},
.name = "control",
@@ -2246,8 +2277,39 @@ static const struct uvcg_config_group_type 
uvcg_streaming_class_grp_type = {
  * streaming
  */
 
+static ssize_t uvcg_default_streaming_b_interface_number_show(
+   struct config_item *item, char *page)
+{
+   struct config_group *group = to_config_group(item);
+   struct mutex *su_mutex = >cg_subsys->su_mutex;
+   struct config_item *opts_item;
+   struct f_uvc_opts *opts;
+   int result = 0;
+
+   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+   opts_item = item->ci_parent;
+   opts = to_f_uvc_opts(opts_item);
+
+   mutex_lock(>lock);
+   result += sprintf(page, "%u\n", opts->streaming_interface);
+   mutex_unlock(>lock);
+
+   mutex_unlock(su_mutex);
+
+   return result;
+}
+
+UVC_ATTR_RO(uvcg_default_streaming_, b_interface_number, bInterfaceNumber);
+
+static struct configfs_attribute *uvcg_default_streaming_attrs[] = {
+   _default_streaming_attr_b_interface_number,
+   NULL,
+};
+
 static const struct uvcg_config_group_type uvcg_streaming_grp_type = {
.type = {
+   .ct_attrs = uvcg_default_streaming_attrs,
    .ct_owner = THIS_MODULE,
},
.name = "st

[PATCH 7/8] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-07-31 Thread Laurent Pinchart
From: Joel Pepper 

- Add bFrameIndex as a UVCG_FRAME_ATTR_RO for each frame size.
- Automatically assign ascending bFrameIndex to each frame in a format.

Before all "bFrameindex" attributes were set to "1" with no way to
configure the gadget otherwise. This resulted in the host always
negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
After the negotiation the host driver will set the user or application
selected framesize, while the gadget is actually set to the first
framesize.

Now, when the containing format is linked into the streaming header,
iterate over all child frame descriptors and assign ascending indices.
The automatically assigned indices can be read from the new read only
bFrameIndex configsfs attribute in each frame descriptor item.

Signed-off-by: Joel Pepper 
[Simplified documentation, renamed function, blank space update]
Signed-off-by: Laurent Pinchart 
---
 Documentation/ABI/testing/configfs-usb-gadget-uvc |  8 
 drivers/usb/gadget/function/uvc_configfs.c| 56 +++
 2 files changed, 64 insertions(+)

diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc 
b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 9896c8aa0e14..1efeb2e835ea 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -181,6 +181,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific MJPEG frame descriptors
 
+   bFrameIndex - unique id for this framedescriptor;
+   only defined after parent format is
+   linked into the streaming header;
+   read-only
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
@@ -232,6 +236,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific uncompressed frame descriptors
 
+   bFrameIndex - unique id for this framedescriptor;
+   only defined after parent format is
+   linked into the streaming header;
+   read-only
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 90de6418209b..9af4cda27865 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -841,6 +841,8 @@ static struct uvcg_streaming_header 
*to_uvcg_streaming_header(struct config_item
return container_of(item, struct uvcg_streaming_header, item);
 }
 
+static void uvcg_format_set_indices(struct config_group *fmt);
+
 static int uvcg_streaming_header_allow_link(struct config_item *src,
struct config_item *target)
 {
@@ -888,6 +890,8 @@ static int uvcg_streaming_header_allow_link(struct 
config_item *src,
if (!target_fmt)
goto out;
 
+   uvcg_format_set_indices(to_config_group(target));
+
format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
if (!format_ptr) {
ret = -ENOMEM;
@@ -1126,6 +1130,41 @@ end: 
\
\
 UVC_ATTR(uvcg_frame_, cname, aname);
 
+static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
+char *page)
+{
+   struct uvcg_frame *f = to_uvcg_frame(item);
+   struct uvcg_format *fmt;
+   struct f_uvc_opts *opts;
+   struct config_item *opts_item;
+   struct config_item *fmt_item;
+   struct mutex *su_mutex = >item.ci_group->cg_subsys->su_mutex;
+   int result;
+
+   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+   fmt_item = f->item.ci_parent;
+   fmt = to_uvcg_format(fmt_item);
+
+   if (!fmt->linked) {
+   result = -EBUSY;
+   goto out;
+   }
+
+   opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
+   opts = to_f_uvc_opts(opts_item);
+
+   mutex_lock(>lock);
+   result = sprintf(page, "%d\n", f->frame.b_frame_index);
+   mutex_unlock(>lock);
+
+out:
+   mutex_unlock(su_mutex);
+   return result;
+}
+
+UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
+
 #define noop_conversion(x) (x)
 
 UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
@@ -1274,6 +1313,7 @@ static

[PATCH 2/8] usb: gadget: uvc: configfs: Add section header comments

2018-07-31 Thread Laurent Pinchart
The UVC configfs implementation is large and difficult to navigate. Add
a bit more air to the code to make it easier to read.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_configfs.c | 120 ++---
 1 file changed, 91 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 1df94b25abe1..dbc95c9558de 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -12,6 +12,10 @@
 #include "u_uvc.h"
 #include "uvc_configfs.h"
 
+/* 
-
+ * Global Utility Structures and Macros
+ */
+
 #define UVCG_STREAMING_CONTROL_SIZE1
 
 #define UVC_ATTR(prefix, cname, aname) \
@@ -37,7 +41,11 @@ static inline struct f_uvc_opts *to_f_uvc_opts(struct 
config_item *item)
func_inst.group);
 }
 
-/* control/header/ */
+/* 
-
+ * control/header/
+ * control/header
+ */
+
 DECLARE_UVC_HEADER_DESCRIPTOR(1);
 
 struct uvcg_control_header {
@@ -161,7 +169,6 @@ static void uvcg_control_header_drop(struct config_group 
*group,
kfree(h);
 }
 
-/* control/header */
 static struct config_group uvcg_control_header_grp;
 
 static struct configfs_group_operations uvcg_control_header_grp_ops = {
@@ -174,7 +181,10 @@ static const struct config_item_type 
uvcg_control_header_grp_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* control/processing/default */
+/* 
-
+ * control/processing/default
+ */
+
 static struct config_group uvcg_default_processing_grp;
 
 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv)   \
@@ -260,16 +270,20 @@ static const struct config_item_type 
uvcg_default_processing_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* struct uvcg_processing {}; */
+/* 
-
+ * control/processing
+ */
 
-/* control/processing */
 static struct config_group uvcg_processing_grp;
 
 static const struct config_item_type uvcg_processing_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control/terminal/camera/default */
+/* 
-
+ * control/terminal/camera/default
+ */
+
 static struct config_group uvcg_default_camera_grp;
 
 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv)   \
@@ -366,16 +380,20 @@ static const struct config_item_type 
uvcg_default_camera_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* struct uvcg_camera {}; */
+/* 
-
+ * control/terminal/camera
+ */
 
-/* control/terminal/camera */
 static struct config_group uvcg_camera_grp;
 
 static const struct config_item_type uvcg_camera_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control/terminal/output/default */
+/* 
-
+ * control/terminal/output/default
+ */
+
 static struct config_group uvcg_default_output_grp;
 
 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv)   \
@@ -433,23 +451,30 @@ static const struct config_item_type 
uvcg_default_output_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* struct uvcg_output {}; */
+/* 
-
+ * control/terminal/output
+ */
 
-/* control/terminal/output */
 static struct config_group uvcg_output_grp;
 
 static const struct config_item_type uvcg_output_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control/terminal */
+/* 
-
+ * control/terminal
+ */
+
 static struct config_group uvcg_terminal_grp;
 
 static const struct config_item_type uvcg_terminal_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control/class/{fs} */
+/* 
-
+ * control/class/{fs|ss}
+ */
+
 static struct config_group uvcg_control_class_fs_grp;
 static struct config_group uvcg_control_class_ss_grp;
 
@@ -552,24 +577,32 @@ static const struct config_item_type 
uvcg_control_class_type = {
.ct_owner   = THIS_MODULE,
 };
 
-/* control/class */
+/* 
-
+ * control/class
+ */
+
 static struct config_group uvcg_control_class_grp;
 
 static const struct config_item_type uvcg_control_class_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-/* control */
+/* 
-
+ * control
+ */
+
 static struct config_group uvcg_control_

[PATCH 0/8] usb: gadget: uvc: Improve configfs support

2018-07-31 Thread Laurent Pinchart
Hello,

This patch series reworks the UVC gadget function configfs implementation to
support multiple UVC functions in a single device and 

The first two patches simplify the code (01/08) and improve readability
(02/08).

The series then moves to dynamically allocating all configfs groups (03/08) to
support multiple instances. As a consequence we have to expose the interface
numbers through new configfs attributes (04/08) in order to let the userspace
helper application discover them.

The next three patches add and document new bFormatIndex (05/08 and 06/08) and
bFrameIndex (07/08) configfs attributes to expose indices of UVC format and
frame descriptors to userspace, allowing their dynamic discovery.

The last patch finally fixes a bug that allowed modification of descriptors
after linking them (08/08).

Felipe, all this is based on top of your testing/next branch, and is a
candidate for v4.20. Please let me know if I should base the patches on a
different branch.

Joel Pepper (2):
  usb: gadget: uvc: configfs: Add bFrameIndex attributes
  usb: gadget: uvc: configfs: Prevent format changes after linking
header

Laurent Pinchart (6):
  usb: gadget: uvc: configfs: Don't wrap groups unnecessarily
  usb: gadget: uvc: configfs: Add section header comments
  usb: gadget: uvc: configfs: Allocate groups dynamically
  usb: gadget: uvc: configfs: Add interface number attributes
  usb: gadget: uvc: configfs: Add bFormatIndex attributes
  usb: gadget: uvc: configfs: Document the bFormatIndex attribute

 Documentation/ABI/testing/configfs-usb-gadget-uvc |  16 +
 drivers/usb/gadget/function/f_uvc.c   |  10 +-
 drivers/usb/gadget/function/u_uvc.h   |   3 +
 drivers/usb/gadget/function/uvc_configfs.c| 821 +-
 4 files changed, 532 insertions(+), 318 deletions(-)

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/8] usb: gadget: uvc: configfs: Don't wrap groups unnecessarily

2018-07-31 Thread Laurent Pinchart
Various configfs groups (represented by config_group) as wrapped in
structures that they're the only member of. This allows adding other
data fields to groups, but is unnecessarily makes the code more complex.
Remove the outter structures and use config_group directly to simplify
the code. Groups can still be wrapped individually in the future if
other data fields need to be added.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_configfs.c | 302 +++--
 1 file changed, 117 insertions(+), 185 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index b51f0d278826..1df94b25abe1 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -162,9 +162,7 @@ static void uvcg_control_header_drop(struct config_group 
*group,
 }
 
 /* control/header */
-static struct uvcg_control_header_grp {
-   struct config_group group;
-} uvcg_control_header_grp;
+static struct config_group uvcg_control_header_grp;
 
 static struct configfs_group_operations uvcg_control_header_grp_ops = {
.make_item  = uvcg_control_header_make,
@@ -177,31 +175,22 @@ static const struct config_item_type 
uvcg_control_header_grp_type = {
 };
 
 /* control/processing/default */
-static struct uvcg_default_processing {
-   struct config_group group;
-} uvcg_default_processing;
-
-static inline struct uvcg_default_processing
-*to_uvcg_default_processing(struct config_item *item)
-{
-   return container_of(to_config_group(item),
-   struct uvcg_default_processing, group);
-}
+static struct config_group uvcg_default_processing_grp;
 
 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv)   \
 static ssize_t uvcg_default_processing_##cname##_show( \
struct config_item *item, char *page)   \
 {  \
-   struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
+   struct config_group *group = to_config_group(item); \
struct f_uvc_opts *opts;\
struct config_item *opts_item;  \
-   struct mutex *su_mutex = >group.cg_subsys->su_mutex;\
+   struct mutex *su_mutex = >cg_subsys->su_mutex;   \
struct uvc_processing_unit_descriptor *pd;  \
int result; \
\
mutex_lock(su_mutex); /* for navigating configfs hierarchy */   \
\
-   opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;  \
+   opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item);\
pd = >uvc_processing; \
\
@@ -229,17 +218,17 @@ UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 
identity_conv);
 static ssize_t uvcg_default_processing_bm_controls_show(
struct config_item *item, char *page)
 {
-   struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
+   struct config_group *group = to_config_group(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
-   struct mutex *su_mutex = >group.cg_subsys->su_mutex;
+   struct mutex *su_mutex = >cg_subsys->su_mutex;
struct uvc_processing_unit_descriptor *pd;
int result, i;
char *pg = page;
 
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
 
-   opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;
+   opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
pd = >uvc_processing;
 
@@ -274,40 +263,29 @@ static const struct config_item_type 
uvcg_default_processing_type = {
 /* struct uvcg_processing {}; */
 
 /* control/processing */
-static struct uvcg_processing_grp {
-   struct config_group group;
-} uvcg_processing_grp;
+static struct config_group uvcg_processing_grp;
 
 static const struct config_item_type uvcg_processing_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
 /* control/terminal/camera/default */
-static struct uvcg_default_camera {
-   struct config_group group;
-} uvcg_default_camera;
-
-static inline struct uvcg_default_camera
-*to_uvcg_default_camera(struct config_item *item)
-{
-   return container_of(to_config_group(item),
-   struct uvcg_default_camera, group);
-}
+static struct config_group uvcg_default_

[PATCH 3/8] usb: gadget: uvc: configfs: Allocate groups dynamically

2018-07-31 Thread Laurent Pinchart
The UVC configfs implementation creates all groups as global static
variables. This prevents creationg of multiple UVC function instances,
as they would all require their own configfs group instances.

Fix this by allocating all groups dynamically. To avoid duplicating code
around, extend the config_item_type structure with group name and
children, and implement helper functions to create children
automatically for most groups.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/f_uvc.c|   8 +-
 drivers/usb/gadget/function/uvc_configfs.c | 480 +
 2 files changed, 282 insertions(+), 206 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uvc.c 
b/drivers/usb/gadget/function/f_uvc.c
index d8ce7868fe22..95cb1b5f5ffe 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -792,6 +792,7 @@ static struct usb_function_instance *uvc_alloc_inst(void)
struct uvc_output_terminal_descriptor *od;
struct uvc_color_matching_descriptor *md;
struct uvc_descriptor_header **ctl_cls;
+   int ret;
 
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
@@ -868,7 +869,12 @@ static struct usb_function_instance *uvc_alloc_inst(void)
opts->streaming_interval = 1;
opts->streaming_maxpacket = 1024;
 
-   uvcg_attach_configfs(opts);
+   ret = uvcg_attach_configfs(opts);
+   if (ret < 0) {
+   kfree(opts);
+   return ERR_PTR(ret);
+   }
+
return >func_inst;
 }
 
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index dbc95c9558de..e019ea317c7a 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -41,6 +41,49 @@ static inline struct f_uvc_opts *to_f_uvc_opts(struct 
config_item *item)
func_inst.group);
 }
 
+struct uvcg_config_group_type {
+   struct config_item_type type;
+   const char *name;
+   const struct uvcg_config_group_type **children;
+   int (*create_children)(struct config_group *group);
+};
+
+static int uvcg_config_create_group(struct config_group *parent,
+   const struct uvcg_config_group_type *type);
+
+static int uvcg_config_create_children(struct config_group *group,
+   const struct uvcg_config_group_type *type)
+{
+   const struct uvcg_config_group_type **child;
+   int ret;
+
+   if (type->create_children)
+   return type->create_children(group);
+
+   for (child = type->children; child && *child; ++child) {
+   ret = uvcg_config_create_group(group, *child);
+   if (ret < 0)
+   return ret;
+   }
+
+   return 0;
+}
+
+static int uvcg_config_create_group(struct config_group *parent,
+   const struct uvcg_config_group_type *type)
+{
+   struct config_group *group;
+
+   group = kzalloc(sizeof(*group), GFP_KERNEL);
+   if (!group)
+   return -ENOMEM;
+
+   config_group_init_type_name(group, type->name, >type);
+   configfs_add_default_group(group, parent);
+
+   return uvcg_config_create_children(group, type);
+}
+
 /* 
-
  * control/header/
  * control/header
@@ -169,24 +212,23 @@ static void uvcg_control_header_drop(struct config_group 
*group,
kfree(h);
 }
 
-static struct config_group uvcg_control_header_grp;
-
 static struct configfs_group_operations uvcg_control_header_grp_ops = {
.make_item  = uvcg_control_header_make,
.drop_item  = uvcg_control_header_drop,
 };
 
-static const struct config_item_type uvcg_control_header_grp_type = {
-   .ct_group_ops   = _control_header_grp_ops,
-   .ct_owner   = THIS_MODULE,
+static const struct uvcg_config_group_type uvcg_control_header_grp_type = {
+   .type = {
+   .ct_group_ops   = _control_header_grp_ops,
+   .ct_owner   = THIS_MODULE,
+   },
+   .name = "header",
 };
 
 /* 
-
  * control/processing/default
  */
 
-static struct config_group uvcg_default_processing_grp;
-
 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv)   \
 static ssize_t uvcg_default_processing_##cname##_show( \
struct config_item *item, char *page)   \
@@ -265,27 +307,33 @@ static struct configfs_attribute 
*uvcg_default_processing_attrs[] = {
NULL,
 };
 
-static const struct config_item_type uvcg_default_processing_type = {
-   .ct_attrs   = uvcg_default_processing_attrs,
-   .ct_owner   = THIS_MODULE,
+static const struct uvcg_config_group_typ

[PATCH 5/8] usb: gadget: uvc: configfs: Add bFormatIndex attributes

2018-07-31 Thread Laurent Pinchart
The UVC format description are numbered using the descriptor's
bFormatIndex field. The index is used in UVC requests, and is thus
needed to handle requests in userspace. Make it dynamically discoverable
by exposing it in a bFormatIndex configfs attribute of the uncompressed
and mjpeg format config items.

The bFormatIndex value exposed through the attribute is stored in the
config item private data. However, that value is never set: the driver
instead computes the bFormatIndex value when linking the stream class
header in the configfs hierarchy and stores it directly in the class
descriptors in a separate structure. In order to expose the value
through the configfs attribute, store it in the config item private data
as well. This results in a small code simplification.

Signed-off-by: Laurent Pinchart 
---
 drivers/usb/gadget/function/uvc_configfs.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 801117686108..90de6418209b 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1517,6 +1517,7 @@ UVC_ATTR(uvcg_uncompressed_, cname, aname);
 
 #define identity_conv(x) (x)
 
+UVCG_UNCOMPRESSED_ATTR_RO(b_format_index, bFormatIndex, identity_conv);
 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, identity_conv);
 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex,
   identity_conv);
@@ -1547,6 +1548,7 @@ uvcg_uncompressed_bma_controls_store(struct config_item 
*item,
 UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
 
 static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
+   _uncompressed_attr_b_format_index,
_uncompressed_attr_guid_format,
_uncompressed_attr_b_bits_per_pixel,
_uncompressed_attr_b_default_frame_index,
@@ -1724,6 +1726,7 @@ UVC_ATTR(uvcg_mjpeg_, cname, aname)
 
 #define identity_conv(x) (x)
 
+UVCG_MJPEG_ATTR_RO(b_format_index, bFormatIndex, identity_conv);
 UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex,
   identity_conv);
 UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, identity_conv);
@@ -1754,6 +1757,7 @@ uvcg_mjpeg_bma_controls_store(struct config_item *item,
 UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
 
 static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
+   _mjpeg_attr_b_format_index,
_mjpeg_attr_b_default_frame_index,
_mjpeg_attr_bm_flags,
_mjpeg_attr_b_aspect_ratio_x,
@@ -2070,24 +2074,22 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, 
void *priv3, int n,
struct uvcg_format *fmt = priv1;
 
if (fmt->type == UVCG_UNCOMPRESSED) {
-   struct uvc_format_uncompressed *unc = *dest;
struct uvcg_uncompressed *u =
container_of(fmt, struct uvcg_uncompressed,
 fmt);
 
+   u->desc.bFormatIndex = n + 1;
+   u->desc.bNumFrameDescriptors = fmt->num_frames;
memcpy(*dest, >desc, sizeof(u->desc));
*dest += sizeof(u->desc);
-   unc->bNumFrameDescriptors = fmt->num_frames;
-   unc->bFormatIndex = n + 1;
} else if (fmt->type == UVCG_MJPEG) {
-   struct uvc_format_mjpeg *mjp = *dest;
struct uvcg_mjpeg *m =
container_of(fmt, struct uvcg_mjpeg, fmt);
 
+   m->desc.bFormatIndex = n + 1;
+   m->desc.bNumFrameDescriptors = fmt->num_frames;
memcpy(*dest, >desc, sizeof(m->desc));
*dest += sizeof(m->desc);
-   mjp->bNumFrameDescriptors = fmt->num_frames;
-   mjp->bFormatIndex = n + 1;
} else {
    return -EINVAL;
}
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/8] usb: gadget: uvc: configfs: Document the bFormatIndex attribute

2018-07-31 Thread Laurent Pinchart
Document for the bFormatIndex attribute of the format descriptors is
missing. Add it.

Signed-off-by: Laurent Pinchart 
---
 Documentation/ABI/testing/configfs-usb-gadget-uvc | 8 
 1 file changed, 8 insertions(+)

diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc 
b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 9281e2aa38df..9896c8aa0e14 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -160,6 +160,10 @@ Description:   Specific MJPEG format descriptors
 
All attributes read only,
except bmaControls and bDefaultFrameIndex:
+   bFormatIndex- unique id for this format descriptor;
+   only defined after parent header is
+   linked into the streaming class;
+   read-only
bmaControls - this format's data for bmaControls in
the streaming header
bmInterfaceFlags- specifies interlace information,
@@ -204,6 +208,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific uncompressed format descriptors
 
+   bFormatIndex- unique id for this format descriptor;
+   only defined after parent header is
+   linked into the streaming class;
+   read-only
bmaControls - this format's data for bmaControls in
the streaming header
bmInterfaceFlags- specifies interlace information,
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v7] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-07-31 Thread Laurent Pinchart
Hi Felipe,

On Thursday, 26 July 2018 13:49:07 EEST Felipe Balbi wrote:
> Laurent Pinchart  writes:
> > From: Joel Pepper 
> > 
> > - Add bFrameIndex as a UVCG_FRAME_ATTR_RO for each frame size.
> > - Automatically assign ascending bFrameIndex to each frame in a format.
> > 
> > Before all "bFrameindex" attributes were set to "1" with no way to
> > configure the gadget otherwise. This resulted in the host always
> > negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
> > After the negotiation the host driver will set the user or application
> > selected framesize, while the gadget is actually set to the first
> > framesize.
> > 
> > Now, when the containing format is linked into the streaming header,
> > iterate over all child frame descriptors and assign ascending indices.
> > The automatically assigned indices can be read from the new read only
> > bFrameIndex configsfs attribute in each frame descriptor item.
> > 
> > Signed-off-by: Joel Pepper 
> > [Simplified documentation, renamed function, blank space update]
> > Signed-off-by: Laurent Pinchart 
> 
> please rebase on testing/next, but give me a couple hours to go through
> the rest of my inbox first ;)

I will. Have you had time to go through the rest of your inbox now ? It's been 
a few hours already I suppose :-)

> checking file Documentation/ABI/testing/configfs-usb-gadget-uvc
> Hunk #1 succeeded at 177 (offset -4 lines).
> Hunk #2 succeeded at 228 (offset -8 lines).
> checking file drivers/usb/gadget/function/uvc_configfs.c
> Hunk #1 succeeded at 720 (offset -121 lines).
> Hunk #2 succeeded at 757 (offset -133 lines).
> Hunk #3 succeeded at 996 (offset -137 lines).
> Hunk #4 succeeded at 1179 (offset -137 lines).
> Hunk #5 FAILED at 1395.
> 1 out of 5 hunks FAILED

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: MUSB issue

2018-07-02 Thread Laurent Pinchart
Hi Alan,

On Monday, 2 July 2018 18:13:27 EEST Alan Stern wrote:
> On Mon, 2 Jul 2018, Paul Elder wrote:
> > Hello Felipe,
> > 
> > We have discovered an issue in MUSB gadget when receiving control OUT
> > transfers. I have specifically observed it very frequently on the second
> > SET_CUR UVC request when trying to stream video with yavta from a UVC
> > gadget.
> > 
> > What happens is that in the DATA phase, the controller copies the
> > incoming data to FIFO which generates an interrupt (as per the docs),
> > then the interrupt handler (actually ep0_rxstate) sends a stall because
> > there is no usb_request to put the data into.
> > 
> > Currently this usb_request is supposed to come from userspace by ioctl
> > UVCIOC_SEND_RESPONSE, which means that (more often than not) if the
> > interrupt corresponding to the DATA phase comes before userspace has a
> > chance to call the ioctl (or before the ioctl handler has a chance to
> > finish), then it will send a stall (usbmon ends with EPIPE).
> 
> Shouldn't the UDC send a NAK install of a STALL under these
> circumstances?  In fact, shouldn't the controller not even bother to
> copy the incoming data to its FIFO?
> 
> I realize the MUSB hardware has a number of limitations, but this seems
> a little peculiar.

Those are questions I've asked myself when trying to help Paul with this 
issue. I realized that I couldn't tell whether MUSB was doing the right thing, 
as I didn't know what the UDC API required.

When validating a control OUT request we need to validate both the data part 
of the SETUP phase (bRequest, bRequestType, wValue, wIndex) and the data part 
of the DATA phase. In the case of the UVC gadget, both validation occurs in 
userspace, so the SETUP validation can't be performed synchronously with the 
function's .setup() handler.

In case of control writes, the STALL handshake can be returned in either the 
DATA phase or the STATUS phase (as far as I understand the USB specification 
doesn't indicate in which use cases it is appropriate to return a STALL 
handshake in the DATA or STATUS phase). As the data validation can obviously 
only be performed after the data is received, I assume that signaling a data 
error through a STALL handshake can only be performed in the STATUS stage. 
Signaling a setup error, on the other hand, could be done in either phase.

The question is thus what options does the USB gadget API offer function 
drivers to STALL the control transfer in the DATA or STATUS phase. As far as I 
can tell, this can be done by returning an error from the .setup() handler (in 
which case I suppose the DATA stage will be STALLed), or calling 
usb_ep_set_halt() before the request completion handler for the DATA stage 
returns. Is that right ? Are there other mechanisms ? If there are no other 
mechanism, I won't be able to validate the DATA stage in userspace as I can 
only send the data to userspace in the DATA stage request completion handler, 
and have to then return before receiving a response from userspace.

After clarifying the API (and possibly extending it...), let's move to the 
MUSB driver and see how to fix it.

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-06-12 Thread Laurent Pinchart
From: Joel Pepper 

- Add bFrameIndex as a UVCG_FRAME_ATTR_RO for each frame size.
- Automatically assign ascending bFrameIndex to each frame in a format.

Before all "bFrameindex" attributes were set to "1" with no way to
configure the gadget otherwise. This resulted in the host always
negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
After the negotiation the host driver will set the user or application
selected framesize, while the gadget is actually set to the first
framesize.

Now, when the containing format is linked into the streaming header,
iterate over all child frame descriptors and assign ascending indices.
The automatically assigned indices can be read from the new read only
bFrameIndex configsfs attribute in each frame descriptor item.

Signed-off-by: Joel Pepper 
[Simplified documentation, renamed function, blank space update]
Signed-off-by: Laurent Pinchart 
---
 Documentation/ABI/testing/configfs-usb-gadget-uvc |  8 
 drivers/usb/gadget/function/uvc_configfs.c| 56 +++
 2 files changed, 64 insertions(+)

Hi Joel,

What do you think about this patch ? It retains your approach and
addresses the few minor reviw comments I sent.

diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc 
b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 9896c8aa0e14..1efeb2e835ea 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -181,6 +181,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific MJPEG frame descriptors
 
+   bFrameIndex - unique id for this framedescriptor;
+   only defined after parent format is
+   linked into the streaming header;
+   read-only
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
@@ -232,6 +236,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific uncompressed frame descriptors
 
+   bFrameIndex - unique id for this framedescriptor;
+   only defined after parent format is
+   linked into the streaming header;
+   read-only
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 5c3ea5f89201..cac249e8a7ec 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -841,6 +841,8 @@ static struct uvcg_streaming_header 
*to_uvcg_streaming_header(struct config_item
return container_of(item, struct uvcg_streaming_header, item);
 }
 
+static void uvcg_format_set_indices(struct config_group *fmt);
+
 static int uvcg_streaming_header_allow_link(struct config_item *src,
struct config_item *target)
 {
@@ -888,6 +890,8 @@ static int uvcg_streaming_header_allow_link(struct 
config_item *src,
if (!target_fmt)
goto out;
 
+   uvcg_format_set_indices(to_config_group(target));
+
format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
if (!format_ptr) {
ret = -ENOMEM;
@@ -1129,6 +1133,41 @@ end: 
\
\
 UVC_ATTR(uvcg_frame_, cname, aname);
 
+static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
+char *page)
+{
+   struct uvcg_frame *f = to_uvcg_frame(item);
+   struct uvcg_format *fmt;
+   struct f_uvc_opts *opts;
+   struct config_item *opts_item;
+   struct config_item *fmt_item;
+   struct mutex *su_mutex = >item.ci_group->cg_subsys->su_mutex;
+   int result;
+
+   mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+   fmt_item = f->item.ci_parent;
+   fmt = to_uvcg_format(fmt_item);
+
+   if (!fmt->linked) {
+   result = -EBUSY;
+   goto out;
+   }
+
+   opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
+   opts = to_f_uvc_opts(opts_item);
+
+   mutex_lock(>lock);
+   result = sprintf(page, "%d\n", f->frame.b_frame_index);
+   mutex_unlock(>lock);
+
+out:
+   mutex_unlock(su_mutex);
+   return result;
+}
+
+UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
+
 #d

Re: [PATCH 2/2] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-06-12 Thread Laurent Pinchart
Hi Joel,

On Sunday, 10 June 2018 14:06:28 EEST Joel Pepper wrote:
> @Laurent, I accidentally hit "Reply" instead of "Reply All", please
> disregard the previous copy of this email
> 
> Hi Laurent and Paul,
> 
> On 08.06.2018 21:16, Laurent Pinchart wrote:
> > Hi Joel and Paul,
> > 
> > On Friday, 8 June 2018 22:12:56 EEST Laurent Pinchart wrote:
> >> From: Paul Elder 
> >> 
> >> The UVC frame descriptions are numbered using the descriptor's
> >> bFrameIndex field. The index is used in UVC requests, and is thus
> >> needed to handle requests in userspace. Make it dynamically discoverable
> >> by exposing it in a bFrameIndex configfs attribute of the frame
> >> config item.
> >> 
> >> However, the bFrameIndex value is never set to begin with. Set these
> >> values when linking the stream class header in the configfs hierarchy,
> >> and store it in the config item private data.
> >> 
> >> Signed-off-by: Paul Elder 
> >> ---
> >> 
> >>  drivers/usb/gadget/function/uvc_configfs.c | 10 --
> >>  1 file changed, 8 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> >> b/drivers/usb/gadget/function/uvc_configfs.c index
> >> 0ad6ea57d0b7..882d9963b244 100644
> >> --- a/drivers/usb/gadget/function/uvc_configfs.c
> >> +++ b/drivers/usb/gadget/function/uvc_configfs.c
> >> @@ -1152,6 +1152,8 @@ UVC_ATTR(uvcg_frame_, cname, aname);
> >> 
> >>  #define noop_conversion(x) (x)
> >> 
> >> +UVCG_FRAME_ATTR_RO(b_frame_index, bFrameIndex, noop_conversion,
> >> +  noop_conversion, 8);
> >> 
> >>  UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
> >>  
> >>noop_conversion, 8);
> >>  
> >>  UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
> >> 
> >> @@ -1298,6 +1300,7 @@ static ssize_t
> >> uvcg_frame_dw_frame_interval_store(struct config_item *item,
> >> UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
> >> 
> >>  static struct configfs_attribute *uvcg_frame_attrs[] = {
> >> 
> >> +  _frame_attr_b_frame_index,
> >> 
> >>_frame_attr_bm_capabilities,
> >>_frame_attr_w_width,
> >>_frame_attr_w_height,
> >> 
> >> @@ -2130,12 +2133,15 @@ static int __uvcg_fill_strm(void *priv1, void
> >> *priv2, void *priv3, int n, sizeof(*frm->dw_frame_interval);
> >> 
> >>memcpy(*dest, frm->dw_frame_interval, sz);
> >>*dest += sz;
> >> 
> >> -  if (frm->fmt_type == UVCG_UNCOMPRESSED)
> >> +  if (frm->fmt_type == UVCG_UNCOMPRESSED) {
> >> 
> >>h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
> >>
> >>frm->frame.b_frame_interval_type);
> >> 
> >> -  else if (frm->fmt_type == UVCG_MJPEG)
> >> +  frm->frame.b_frame_index = n + 1;
> >> +  } else if (frm->fmt_type == UVCG_MJPEG) {
> >> 
> >>h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
> >>
> >>frm->frame.b_frame_interval_type);
> >> 
> >> +  frm->frame.b_frame_index = n + 1;
> >> +  }
> >> 
> >>}
> >>break;
> >>}
> > 
> > This approach looks simpler to me than the patch that Joel submitted.
> 
> However,
> 
> > this patch lacks ABI documentation, which is included in Joel's patch.
> > 
> > Joel, as you were first, I propose taking your patch and modifying it
> 
> with the
> 
> > approach followed here, using the UVCG_FRAME_ATTR_RO macro and setting
> > b_frame_index in __uvcg_fill_strm(). Would that be OK with you ? Or is
> 
> there a
> 
> > reason why the approach taken in your patch would be better ?
> 
> I've compared Paul's implementation to mine, and as far as I can tell,
> they are functionally equivalent  except for two points:
> 
> 1) I specifically opted against using a generic UVCG_FRAME_ATTR_RO
> macro, because the index has no well defined value until they are all
> set at once, as such reading the attribute beforehand should return
> -EBUSY before that point (instead of 1 for all indexes, which would be
> the case now). All other attributes can be read immediately after
> creati

[PATCH] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-06-08 Thread Laurent Pinchart
From: Joel Pepper 

- Add bFrameIndex as a UVCG_FRAME_ATTR_RO for each frame size.
- Automatically assign ascending bFrameIndex to each frame in a format.

Before all "bFrameindex" attributes were set to "1" with no way to
configure the gadget otherwise. This resulted in the host always
negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
After the negotiation the host driver will set the user or application
selected framesize, while the gadget is actually set to the first
framesize.

Now, when the containing format is linked into the streaming header,
iterate over all child frame descriptors and assign ascending indices.
The automatically assigned indices can be read from the new read only
bFrameIndex configsfs attribute in each frame descriptor item.

Signed-off-by: Joel Pepper 
Signed-off-by: Paul Elder 
[Merge Joel's documentation and Paul's code]
Signed-off-by: Laurent Pinchart 
---
 Documentation/ABI/testing/configfs-usb-gadget-uvc |  8 
 drivers/usb/gadget/function/uvc_configfs.c| 10 --
 2 files changed, 16 insertions(+), 2 deletions(-)

This is the mix of Paul's and Joel's patches. I've also simplified the
ABI documentation by omitting the changelog date and kernel version as
seems to be the common practice when adding new attributes to existing
directories.

diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc 
b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 9281e2aa38df..bee6ab72e6b1 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -177,6 +177,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific MJPEG frame descriptors
 
+   bFrameIndex - unique id for this framedescriptor;
+   only defined after parent format is
+   linked into the streaming header;
+   read-only
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
@@ -224,6 +228,10 @@ Date:  Dec 2014
 KernelVersion: 4.0
 Description:   Specific uncompressed frame descriptors
 
+   bFrameIndex - unique id for this framedescriptor;
+   only defined after parent format is
+   linked into the streaming header;
+   read-only
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 1122659ccfe6..1645be415933 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1155,6 +1155,8 @@ UVC_ATTR(uvcg_frame_, cname, aname);
 
 #define noop_conversion(x) (x)
 
+UVCG_FRAME_ATTR_RO(b_frame_index, bFrameIndex, noop_conversion,
+   noop_conversion, 8);
 UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
noop_conversion, 8);
 UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
@@ -1301,6 +1303,7 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct 
config_item *item,
 UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
 
 static struct configfs_attribute *uvcg_frame_attrs[] = {
+   _frame_attr_b_frame_index,
_frame_attr_bm_capabilities,
_frame_attr_w_width,
_frame_attr_w_height,
@@ -2133,12 +2136,15 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, 
void *priv3, int n,
sizeof(*frm->dw_frame_interval);
memcpy(*dest, frm->dw_frame_interval, sz);
*dest += sz;
-   if (frm->fmt_type == UVCG_UNCOMPRESSED)
+   if (frm->fmt_type == UVCG_UNCOMPRESSED) {
h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
frm->frame.b_frame_interval_type);
-   else if (frm->fmt_type == UVCG_MJPEG)
+   frm->frame.b_frame_index = n + 1;
+   } else if (frm->fmt_type == UVCG_MJPEG) {
h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
frm->frame.b_frame_interval_type);
+   frm->frame.b_frame_index = n + 1;
+   }
    }
break;
}
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-06-08 Thread Laurent Pinchart
Hi Joel and Paul,

On Friday, 8 June 2018 22:12:56 EEST Laurent Pinchart wrote:
> From: Paul Elder 
> 
> The UVC frame descriptions are numbered using the descriptor's
> bFrameIndex field. The index is used in UVC requests, and is thus
> needed to handle requests in userspace. Make it dynamically discoverable
> by exposing it in a bFrameIndex configfs attribute of the frame
> config item.
> 
> However, the bFrameIndex value is never set to begin with. Set these
> values when linking the stream class header in the configfs hierarchy,
> and store it in the config item private data.
> 
> Signed-off-by: Paul Elder 
> ---
>  drivers/usb/gadget/function/uvc_configfs.c | 10 --
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> b/drivers/usb/gadget/function/uvc_configfs.c index
> 0ad6ea57d0b7..882d9963b244 100644
> --- a/drivers/usb/gadget/function/uvc_configfs.c
> +++ b/drivers/usb/gadget/function/uvc_configfs.c
> @@ -1152,6 +1152,8 @@ UVC_ATTR(uvcg_frame_, cname, aname);
> 
>  #define noop_conversion(x) (x)
> 
> +UVCG_FRAME_ATTR_RO(b_frame_index, bFrameIndex, noop_conversion,
> + noop_conversion, 8);
>  UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
>   noop_conversion, 8);
>  UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
> @@ -1298,6 +1300,7 @@ static ssize_t
> uvcg_frame_dw_frame_interval_store(struct config_item *item,
> UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
> 
>  static struct configfs_attribute *uvcg_frame_attrs[] = {
> + _frame_attr_b_frame_index,
>   _frame_attr_bm_capabilities,
>   _frame_attr_w_width,
>   _frame_attr_w_height,
> @@ -2130,12 +2133,15 @@ static int __uvcg_fill_strm(void *priv1, void
> *priv2, void *priv3, int n, sizeof(*frm->dw_frame_interval);
>   memcpy(*dest, frm->dw_frame_interval, sz);
>   *dest += sz;
> - if (frm->fmt_type == UVCG_UNCOMPRESSED)
> + if (frm->fmt_type == UVCG_UNCOMPRESSED) {
>   h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
>   frm->frame.b_frame_interval_type);
> - else if (frm->fmt_type == UVCG_MJPEG)
> + frm->frame.b_frame_index = n + 1;
> + } else if (frm->fmt_type == UVCG_MJPEG) {
>   h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
>   frm->frame.b_frame_interval_type);
> + frm->frame.b_frame_index = n + 1;
> + }
>   }
>   break;
>   }

This approach looks simpler to me than the patch that Joel submitted. However, 
this patch lacks ABI documentation, which is included in Joel's patch.

Joel, as you were first, I propose taking your patch and modifying it with the 
approach followed here, using the UVCG_FRAME_ATTR_RO macro and setting 
b_frame_index in __uvcg_fill_strm(). Would that be OK with you ? Or is there a 
reason why the approach taken in your patch would be better ?

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] usb: gadget: uvc: configfs: add UVCG_FRAME_ATTR_RO

2018-06-08 Thread Laurent Pinchart
From: Paul Elder 

Some attributes of the UVC frame descriptors should be read-only in
configfs, such as bFrameIndex. Add a read-only version of
UVCG_FRAME_ATTR to achieve this.

Signed-off-by: Paul Elder 
---
 drivers/usb/gadget/function/uvc_configfs.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 90de6418209b..0ad6ea57d0b7 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1067,6 +1067,30 @@ static struct uvcg_frame *to_uvcg_frame(struct 
config_item *item)
return container_of(item, struct uvcg_frame, item);
 }
 
+#define UVCG_FRAME_ATTR_RO(cname, aname, to_cpu_endian, to_little_endian, 
bits) \
+static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
+{  \
+   struct uvcg_frame *f = to_uvcg_frame(item); \
+   struct f_uvc_opts *opts;\
+   struct config_item *opts_item;  \
+   struct mutex *su_mutex = >item.ci_group->cg_subsys->su_mutex;\
+   int result; \
+   \
+   mutex_lock(su_mutex); /* for navigating configfs hierarchy */   \
+   \
+   opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
+   opts = to_f_uvc_opts(opts_item);\
+   \
+   mutex_lock(>lock);\
+   result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname));  \
+   mutex_unlock(>lock);  \
+   \
+   mutex_unlock(su_mutex); \
+   return result;  \
+}  \
+   \
+UVC_ATTR_RO(uvcg_frame_, cname, aname);
+
 #define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
 static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
 {      \
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] usb: gadget: uvc: configfs: Add bFrameIndex attributes

2018-06-08 Thread Laurent Pinchart
From: Paul Elder 

The UVC frame descriptions are numbered using the descriptor's
bFrameIndex field. The index is used in UVC requests, and is thus
needed to handle requests in userspace. Make it dynamically discoverable
by exposing it in a bFrameIndex configfs attribute of the frame
config item.

However, the bFrameIndex value is never set to begin with. Set these
values when linking the stream class header in the configfs hierarchy,
and store it in the config item private data.

Signed-off-by: Paul Elder 
---
 drivers/usb/gadget/function/uvc_configfs.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 0ad6ea57d0b7..882d9963b244 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1152,6 +1152,8 @@ UVC_ATTR(uvcg_frame_, cname, aname);
 
 #define noop_conversion(x) (x)
 
+UVCG_FRAME_ATTR_RO(b_frame_index, bFrameIndex, noop_conversion,
+   noop_conversion, 8);
 UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
noop_conversion, 8);
 UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
@@ -1298,6 +1300,7 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct 
config_item *item,
 UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
 
 static struct configfs_attribute *uvcg_frame_attrs[] = {
+   _frame_attr_b_frame_index,
_frame_attr_bm_capabilities,
_frame_attr_w_width,
_frame_attr_w_height,
@@ -2130,12 +2133,15 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, 
void *priv3, int n,
sizeof(*frm->dw_frame_interval);
memcpy(*dest, frm->dw_frame_interval, sz);
*dest += sz;
-   if (frm->fmt_type == UVCG_UNCOMPRESSED)
+   if (frm->fmt_type == UVCG_UNCOMPRESSED) {
h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
frm->frame.b_frame_interval_type);
-   else if (frm->fmt_type == UVCG_MJPEG)
+   frm->frame.b_frame_index = n + 1;
+   } else if (frm->fmt_type == UVCG_MJPEG) {
h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
frm->frame.b_frame_interval_type);
+   frm->frame.b_frame_index = n + 1;
+   }
}
    break;
}
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND][PATCH v6 2/2] usb/gadget/uvc-configfs Fix host unable to negotiate framesizes other than first

2018-06-08 Thread Laurent Pinchart
t; +

No need for a new blank line.

> +static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
> + char *page)
> +{
> + struct uvcg_frame *f = to_uvcg_frame(item);
> + struct uvcg_format *fmt;
> + struct f_uvc_opts *opts;
> + struct config_item *opts_item;
> + struct config_item *fmt_item;
> + struct mutex *su_mutex = >item.ci_group->cg_subsys->su_mutex;
> + int result;
> +
> + mutex_lock(su_mutex); /* for navigating configfs hierarchy */
> +
> + fmt_item = f->item.ci_parent;
> + fmt = to_uvcg_format(fmt_item);
> +
> + if (!fmt->linked) {
> + result = -EBUSY;
> + goto out;
> + }
> +
> + opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
> + opts = to_f_uvc_opts(opts_item);
> +
> + mutex_lock(>lock);
> + result = sprintf(page, "%d\n", f->frame.b_frame_index);
> + mutex_unlock(>lock);
> +
> +out:
> + mutex_unlock(su_mutex);
> + return result;
> +}
> +
> +UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
> +

As we already have UVCG_FRAME_ATTR, should we turn this into a 
UVCG_FRAME_ATTR_RO macro ?

>  #define noop_conversion(x) (x)
> 
> +
> +
>  UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
>   noop_conversion, 8);
>  UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
> @@ -1140,6 +1181,7 @@ UVC_ATTR(uvcg_frame_, dw_frame_interval,
> dwFrameInterval);
> 
>  static struct configfs_attribute *uvcg_frame_attrs[] = {
>   _frame_attr_bm_capabilities,
> + _frame_attr_b_frame_index,
>   _frame_attr_w_width,
>   _frame_attr_w_height,
>   _frame_attr_dw_min_bit_rate,
> @@ -1217,6 +1259,28 @@ static void uvcg_frame_drop(struct config_group
> *group, struct config_item *item mutex_unlock(>lock);
>  }
> 
> +static void __uvcg_fmt_set_indices(struct config_group *fmt)
> +{
> + u8 i = 1;

I think you can simply use an unsigned int.

> + struct list_head *entry;
> + struct config_item *ci;
> + struct uvcg_frame *frm;

You could declare the last two variables inside the loop. I'll let you decide 
on this change, as the function is small and the variables are thus already 
close to the code that uses them.

> +
> + list_for_each(entry, &(fmt->cg_children)) {
> +

No need for a blank line here.

> + ci = container_of(entry, struct config_item, ci_entry);
> +
> + if (ci->ci_type != _frame_type)
> + continue;
> +
> + frm = to_uvcg_frame(ci);
> +     frm->frame.b_frame_index = i;
> + i++;

You could write this

frm->frame.b_frame_index = i++;

> +

And no need for a blank line here either.

> + }
> +

Same here.

> +}
> +
>  /* streaming/uncompressed/ */
>  struct uvcg_uncompressed {
>   struct uvcg_format  fmt;

Can't you set b_frame_index from __uvcg_fill_strm(), in a similar way as the 
b_format_index is set ? I've received a competing implementation from Paul in 
parallel to your patch that does so, I'll post it as a reply to this e-mail to 
discuss which approach is best.

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND][PATCH v6 1/2] usb/gadget/uvc-configfs Fix linked flag in a format not being set when format is linked into streaming header

2018-06-08 Thread Laurent Pinchart
Hi Joel,

Thank you for the patch, and sorry for the late reply.

On Tuesday, 29 May 2018 22:02:12 EEST Joel Pepper wrote:
> While checks are in place to avoid attributes and children of a format
> being manipulated after the format is linked into the streaming header,
> the linked flag was never actually set, invalidating the protections.
> 
> Signed-off-by: Joel Pepper 

This looks good to me, but you might want to shorten the subject line though, 
it's supposed to fit in 72 characters. How about

usb: gadget: uvc: configfs: Prevent format changes after linking header

Apart from that,


Reviewed-by: Laurent Pinchart 

> ---
>  drivers/usb/gadget/function/uvc_configfs.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> b/drivers/usb/gadget/function/uvc_configfs.c index c9b8cc4a..7a98f9f 100644
> --- a/drivers/usb/gadget/function/uvc_configfs.c
> +++ b/drivers/usb/gadget/function/uvc_configfs.c
> @@ -760,6 +760,7 @@ static int uvcg_streaming_header_allow_link(struct
> config_item *src, format_ptr->fmt = target_fmt;
>   list_add_tail(_ptr->entry, _hdr->formats);
>   ++src_hdr->num_fmt;
> + ++target_fmt->linked;
> 
>  out:
>   mutex_unlock(>lock);
> @@ -797,6 +798,8 @@ static void uvcg_streaming_header_drop_link(struct
> config_item *src, break;
>   }
> 
> + --target_fmt->linked;
> +
>  out:
>   mutex_unlock(>lock);
>   mutex_unlock(su_mutex);


-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFT/PATCH 00/38] usb: dwc3: gadget: Rework & Refactoring

2018-05-24 Thread Laurent Pinchart
Hello again,

On Thursday, 24 May 2018 22:59:18 EEST Laurent Pinchart wrote:
> On Friday, 20 April 2018 13:57:23 EEST Felipe Balbi wrote:
> > Bin Liu <b-...@ti.com> writes:
> >>> Felipe Balbi <felipe.ba...@linux.intel.com> writes:
> >>>>>> Bin Liu <b-...@ti.com> writes:
> >>>>>>> On Mon, Apr 09, 2018 at 02:26:14PM +0300, Felipe Balbi wrote:
> >>>>>>>> Hi guys,
> >>>>>>>> 
> >>>>>>>> I've been working on this series for a while now. I feels like
> >>>>>>>> after this series the transfer management code is far easier to
> >>>>>>>> read and understand.
> >>>>>>>> 
> >>>>>>>> Based on my tests, I have no regressions. Tested g_mass_storage
> >>>>>>>> and all of testusb's tests (including ISOC).
> >>>>>>>> 
> >>>>>>>> Patches are also available on dwc3-improve-isoc-endpoints in my
> >>>>>>>> k.org tree. Test reports would be VERY, VERY, VERY welcome. Please
> >>>>>>>> give this a go so we avoid regressions on v4.18.
> >>>>>>> 
> >>>>>>> Have you tested g_webcam? I just tested your
> >>>>>>> dwc3-improve-isoc-endpoints
> >>>>>> 
> >>>>>> for isoc I only tested g_zero.
> >>>>> 
> >>>>> Then writting down details on what I observed probably won't help you
> >>>>> 
> >>>>> :(
> >>> 
> >>> I got webcam running here, it sure _is_ helpful to let me know how you
> >> 
> >> Great!
> >> 
> >>> trigger the problem ;-) Also, high-speed or super-speed?
> >> 
> >> Both. Long story short - super-speed doesn't stream the yuv video,
> >> gadget side kernel prints "VS request completed with status -18."
> >> flooding messages.
> >> 
> >> high-speed does stream the video, but stopping the host application
> >> (both yavta and luvcview) causes gadget side kernel prints error message
> >> (I didn't keep the log). Then restart the host application doesn't
> >> stream the video any more.
> 
> What is your test platform ? I'm using a TI AM574x EVM and I can't get video
> to stream at all in high-speed. Super-speed seems out of question as the
> only port supporting device mode on that board is connect to a DWC3
> instance that is limited to high-speed :-/ I'm testing v4.17-rc5 without
> this patch series applied, please let me know if I should apply it first.

I tried to merge your dwc3-improve-isoc-endpoints branch but it unfortunately 
didn't help. I still can't capture any frame on the host.

With and without your patches I get the following messages in the device's 
kernel log.

- At gadget creation and plug time:

[   12.361591] configfs-gadget gadget: uvc_function_bind
[   16.783801] configfs-gadget gadget: high-speed config #1: c
[   16.790032] configfs-gadget gadget: uvc_function_set_alt(0, 0)
[   16.796166] configfs-gadget gadget: reset UVC Control
[   16.801537] configfs-gadget gadget: uvc_function_set_alt(1, 0)
[   16.818799] configfs-gadget gadget: uvc_function_set_alt(1, 0)

- At stream start time:

[   23.093891] configfs-gadget gadget: uvc_function_set_alt(1, 1)
[   23.103072] configfs-gadget gadget: reset UVC
[   23.111108] dwc3 488d.usb: ep2in: ran out of requests

and everything stops there.

> >> To run the test:
> >> 
> >> gadget side:
> >># modprobe g_webcam (streaming_maxpacket=3072 for super-speed)
> >># uvc-gadget
> >> 
> >> host side:
> >>$ yavta -c -f YUYV -t 1/30 -s 640x360 -n4 /dev/video1, or
> >>$ luvcview -d /dev/video1 -f yuv
> > 
> > okay, found the problem. This is actually a problem on webcam gadget
> > which kills the stream in case of Missed Isoc. The reason why it "works"
> > with dwc3 today is because dwc3, up until now, is really harsh whenever
> > we miss and interval.
> > 
> > Currently we stop the transfer and wait for the next XferNotReady. This
> > may cause us to loose many frames.
> > 
> > I've been talking with Laurent Pinchart (in Cc) about what would be the
> > best way to sort this out and, our conclusion, is that webcam gadget
> > should have a way for a single buffer to be treated as erroneous, but it
> > shouldn't stop the stream.
> > 
> > There's also another error in webcam gadget where default interval,
> > maxburst and maxpacket aren't very good for HS or SS.
> > 
> > Note that streaming_interval is, by default, 1. Which for FS means 1ms,
> > but for HS/SS it means 1 * 125us. So host side is actually polling
> > webcam gadget every uFrame. I got webcam gadget to behave really well
> > with streaming_interval=4 streaming_maxburst=16
> > streaming_maxpacket=3072. With that, in SS, I can get around 100
> > fps. There are a few cases when FPS drops to 33, but that's because it
> > coincides with a missed isoc and webcam stops and restarts the stream.

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFT/PATCH 00/38] usb: dwc3: gadget: Rework & Refactoring

2018-05-24 Thread Laurent Pinchart
Hi Felipe,

On Friday, 20 April 2018 13:57:23 EEST Felipe Balbi wrote:
> Bin Liu <b-...@ti.com> writes:
> >> Felipe Balbi <felipe.ba...@linux.intel.com> writes:
> >>>>> Bin Liu <b-...@ti.com> writes:
> >>>>>> On Mon, Apr 09, 2018 at 02:26:14PM +0300, Felipe Balbi wrote:
> >>>>>>> Hi guys,
> >>>>>>> 
> >>>>>>> I've been working on this series for a while now. I feels like
> >>>>>>> after this series the transfer management code is far easier to
> >>>>>>> read and understand.
> >>>>>>> 
> >>>>>>> Based on my tests, I have no regressions. Tested g_mass_storage
> >>>>>>> and all of testusb's tests (including ISOC).
> >>>>>>> 
> >>>>>>> Patches are also available on dwc3-improve-isoc-endpoints in my
> >>>>>>> k.org tree. Test reports would be VERY, VERY, VERY welcome. Please
> >>>>>>> give this a go so we avoid regressions on v4.18.
> >>>>>> 
> >>>>>> Have you tested g_webcam? I just tested your
> >>>>>> dwc3-improve-isoc-endpoints
> >>>>> 
> >>>>> for isoc I only tested g_zero.
> >>>> 
> >>>> Then writting down details on what I observed probably won't help you
> >>>> :(
> >> 
> >> I got webcam running here, it sure _is_ helpful to let me know how you
> > 
> > Great!
> > 
> >> trigger the problem ;-) Also, high-speed or super-speed?
> > 
> > Both. Long story short - super-speed doesn't stream the yuv video,
> > gadget side kernel prints "VS request completed with status -18."
> > flooding messages.
> > 
> > high-speed does stream the video, but stopping the host application
> > (both yavta and luvcview) causes gadget side kernel prints error message
> > (I didn't keep the log). Then restart the host application doesn't
> > stream the video any more.

What is your test platform ? I'm using a TI AM574x EVM and I can't get video 
to stream at all in high-speed. Super-speed seems out of question as the only 
port supporting device mode on that board is connect to a DWC3 instance that 
is limited to high-speed :-/ I'm testing v4.17-rc5 without this patch series 
applied, please let me know if I should apply it first.

> > To run the test:
> > 
> > gadget side:
> > # modprobe g_webcam (streaming_maxpacket=3072 for super-speed)
> > # uvc-gadget
> > 
> > host side:
> > $ yavta -c -f YUYV -t 1/30 -s 640x360 -n4 /dev/video1, or
> > $ luvcview -d /dev/video1 -f yuv
> 
> okay, found the problem. This is actually a problem on webcam gadget
> which kills the stream in case of Missed Isoc. The reason why it "works"
> with dwc3 today is because dwc3, up until now, is really harsh whenever
> we miss and interval.
> 
> Currently we stop the transfer and wait for the next XferNotReady. This
> may cause us to loose many frames.
> 
> I've been talking with Laurent Pinchart (in Cc) about what would be the
> best way to sort this out and, our conclusion, is that webcam gadget
> should have a way for a single buffer to be treated as erroneous, but it
> shouldn't stop the stream.
> 
> There's also another error in webcam gadget where default interval,
> maxburst and maxpacket aren't very good for HS or SS.
> 
> Note that streaming_interval is, by default, 1. Which for FS means 1ms,
> but for HS/SS it means 1 * 125us. So host side is actually polling
> webcam gadget every uFrame. I got webcam gadget to behave really well
> with streaming_interval=4 streaming_maxburst=16
> streaming_maxpacket=3072. With that, in SS, I can get around 100
> fps. There are a few cases when FPS drops to 33, but that's because it
> coincides with a missed isoc and webcam stops and restarts the stream.

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: gadget: uvc: Expose configuration name through video node

2018-05-24 Thread Laurent Pinchart
Hi Kieran,

Thank you for the patch.

On Thursday, 24 May 2018 19:16:12 EEST Kieran Bingham wrote:
> From: Kieran Bingham <kieran.bing...@ideasonboard.com>
> 
> When utilising multiple instantiations of a UVC gadget on a composite
> device, there is no clear method to link a particular configuration to
> its respective video node.
> 
> Provide a means for identifying the correct video node by exposing the
> name of the function configuration through sysfs.
> 
> Signed-off-by: Kieran Bingham <kieran.bing...@ideasonboard.com>

Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>

> ---
> v2:
>  - Fix commit title (f_uvc -> uvc)
>  - Change identifier file name (now function_name)
>  - Document in ABI
> 
>  .../ABI/testing/configfs-usb-gadget-uvc   |  5 
>  drivers/usb/gadget/function/f_uvc.c   | 24 ++-
>  2 files changed, 28 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc
> b/Documentation/ABI/testing/configfs-usb-gadget-uvc index
> 1ba0d0fda9c0..9281e2aa38df 100644
> --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
> +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
> @@ -263,3 +263,8 @@ Description:  Specific streaming header descriptors
>   is connected
>   bmInfo  - capabilities of this video streaming
>   interface
> +
> +What:
> /sys/class/udc/udc.name/device/gadget/video4linux/video.name/
functio
> n_name +Date: May 2018
> +KernelVersion:   4.19
> +Description: UVC configfs function instance name
> diff --git a/drivers/usb/gadget/function/f_uvc.c
> b/drivers/usb/gadget/function/f_uvc.c index d82cd61676d3..c8627cc698f8
> 100644
> --- a/drivers/usb/gadget/function/f_uvc.c
> +++ b/drivers/usb/gadget/function/f_uvc.c
> @@ -421,10 +421,21 @@ uvc_function_disconnect(struct uvc_device *uvc)
>   * USB probe and disconnect
>   */
> 
> +static ssize_t function_name_show(struct device *dev,
> +   struct device_attribute *attr, char *buf)
> +{
> + struct uvc_device *uvc = dev_get_drvdata(dev);
> +
> + return sprintf(buf, "%s\n", uvc->func.fi->group.cg_item.ci_name);
> +}
> +
> +static DEVICE_ATTR_RO(function_name);
> +
>  static int
>  uvc_register_video(struct uvc_device *uvc)
>  {
>   struct usb_composite_dev *cdev = uvc->func.config->cdev;
> + int ret;
> 
>   /* TODO reference counting. */
>   uvc->vdev.v4l2_dev = >v4l2_dev;
> @@ -437,7 +448,17 @@ uvc_register_video(struct uvc_device *uvc)
> 
>   video_set_drvdata(>vdev, uvc);
> 
> - return video_register_device(>vdev, VFL_TYPE_GRABBER, -1);
> + ret = video_register_device(>vdev, VFL_TYPE_GRABBER, -1);
> + if (ret < 0)
> + return ret;
> +
> + ret = device_create_file(>vdev.dev, _attr_function_name);
> + if (ret < 0) {
> + video_unregister_device(>vdev);
> + return ret;
> + }
> +
> + return 0;
>  }
> 
>  #define UVC_COPY_DESCRIPTOR(mem, dst, desc) \
> @@ -877,6 +898,7 @@ static void uvc_unbind(struct usb_configuration *c,
> struct usb_function *f)
> 
>   INFO(cdev, "%s\n", __func__);
> 
> + device_remove_file(>vdev.dev, _attr_function_name);
>   video_unregister_device(>vdev);
>   v4l2_device_unregister(>v4l2_dev);

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: f_uvc: Expose configuration name through video node

2018-05-24 Thread Laurent Pinchart
Hi Kieran,

Thank you for the patch.

On Wednesday, 23 May 2018 23:39:47 EEST Kieran Bingham wrote:
> From: Kieran Bingham <kieran.bing...@ideasonboard.com>
> 
> When utilising multiple instantiations of a UVC gadget on a composite
> device, there is no clear method to link a particular configuration to
> its respective video node.
> 
> Provide a means for identifying the correct video node by exposing the
> name of the function configuration through sysfs.
> 
> Signed-off-by: Kieran Bingham <kieran.bing...@ideasonboard.com>
> ---
>  drivers/usb/gadget/function/f_uvc.c | 24 +++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/gadget/function/f_uvc.c
> b/drivers/usb/gadget/function/f_uvc.c index 1affa8e3a974..f326d1707633
> 100644
> --- a/drivers/usb/gadget/function/f_uvc.c
> +++ b/drivers/usb/gadget/function/f_uvc.c
> @@ -421,10 +421,21 @@ uvc_function_disconnect(struct uvc_device *uvc)
>   * USB probe and disconnect
>   */
> 
> +static ssize_t config_show(struct device *dev, struct device_attribute
> *attr, + char *buf)
> +{
> + struct uvc_device *uvc = dev_get_drvdata(dev);
> +
> + return sprintf(buf, "%s\n", uvc->func.fi->group.cg_item.ci_name);
> +}
> +
> +static DEVICE_ATTR_RO(config);

You need to document the attribute in Documentation/ABI/.

I wonder whether we should use a more explicit name for the attribute. Maybe 
function_name ? usb_function_name ? usb_configfs_name ? Feel free to propose a 
better option.

> +
>  static int
>  uvc_register_video(struct uvc_device *uvc)
>  {
>   struct usb_composite_dev *cdev = uvc->func.config->cdev;
> + int ret;
> 
>   /* TODO reference counting. */
>   uvc->vdev.v4l2_dev = >v4l2_dev;
> @@ -437,7 +448,17 @@ uvc_register_video(struct uvc_device *uvc)
> 
>   video_set_drvdata(>vdev, uvc);
> 
> - return video_register_device(>vdev, VFL_TYPE_GRABBER, -1);
> + ret = video_register_device(>vdev, VFL_TYPE_GRABBER, -1);
> + if (ret < 0)
> + return ret;
> +
> + ret = device_create_file(>vdev.dev, _attr_config);
> + if (ret < 0) {
> + video_unregister_device(>vdev);
> + return ret;
> + }
> +
> + return 0;
>  }
> 
>  #define UVC_COPY_DESCRIPTOR(mem, dst, desc) \
> @@ -875,6 +896,7 @@ static void uvc_unbind(struct usb_configuration *c,
> struct usb_function *f)
> 
>   INFO(cdev, "%s\n", __func__);
> 
> + device_remove_file(>vdev.dev, _attr_config);
>   video_unregister_device(>vdev);
>   v4l2_device_unregister(>v4l2_dev);

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: gadget: uvc: configfs: Move function to avoid forward declaration

2018-05-23 Thread Laurent Pinchart
The to_f_uvc_opts() function is forward-declared without needing to, as
its definition can simply be moved up in the file. Fix it.

Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/usb/gadget/function/uvc_configfs.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index c9b8cc4aae5a..b51f0d278826 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -31,7 +31,11 @@ static struct configfs_attribute prefix##attr_##cname = { \
.show   = prefix##cname##_show, \
 }
 
-static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item);
+static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
+{
+   return container_of(to_config_group(item), struct f_uvc_opts,
+   func_inst.group);
+}
 
 /* control/header/ */
 DECLARE_UVC_HEADER_DESCRIPTOR(1);
@@ -2105,12 +2109,6 @@ static const struct config_item_type 
uvcg_streaming_grp_type = {
.ct_owner = THIS_MODULE,
 };
 
-static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
-{
-   return container_of(to_config_group(item), struct f_uvc_opts,
-   func_inst.group);
-}
-
 static void uvc_attr_release(struct config_item *item)
 {
struct f_uvc_opts *opts = to_f_uvc_opts(item);
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: uvc: Utilise instance name in video name

2018-05-22 Thread Laurent Pinchart
Hi Kieran,

Thank you for the patch.

On Tuesday, 22 May 2018 18:29:49 EEST Kieran Bingham wrote:
> From: Kieran Bingham <kieran.bing...@ideasonboard.com>
> 
> With multiple UVC gadgets on a composite device, the device names become
> indistinguishable from one another.
> 
> Extend the gadget video name to incorporate the function instance name,
> along side the existing UDC controller name.
> 
> Signed-off-by: Kieran Bingham <kieran.bing...@ideasonboard.com>
> ---
>  drivers/usb/gadget/function/f_uvc.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/gadget/function/f_uvc.c
> b/drivers/usb/gadget/function/f_uvc.c index 1affa8e3a974..65454a31ad68
> 100644
> --- a/drivers/usb/gadget/function/f_uvc.c
> +++ b/drivers/usb/gadget/function/f_uvc.c
> @@ -433,7 +433,9 @@ uvc_register_video(struct uvc_device *uvc)
>   uvc->vdev.release = video_device_release_empty;
>   uvc->vdev.vfl_dir = VFL_DIR_TX;
>   uvc->vdev.lock = >video.mutex;
> - strlcpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name));
> +
> + snprintf(uvc->vdev.name, sizeof(uvc->vdev.name), "%s:%s",
> +  cdev->gadget->name, uvc->func.fi->group.cg_item.ci_name);

If the function is instantiated from the legacy g_webcam, the whole group 
structure will be zero, so ci_name will be empty. I think you should omit the 
":" in that case.

I also wonder whether the vdev.name field will always be long enough. If we 
can't guarantee that, would it make sense to instead expose the config item 
name through a custom sysfs property for the video device ?

>   video_set_drvdata(>vdev, uvc);

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] usb: gadget: uvc: Move trace parameter to function module

2018-05-21 Thread Laurent Pinchart
The trace module parameter controls output of debugging messages in the
UVC function driver. Move it from the webcam module to the UVC function
module where it belongs. This allows ConfigFS-based UVC gadgets to
control tracing.

Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/usb/gadget/function/f_uvc.c | 2 ++
 drivers/usb/gadget/function/u_uvc.h | 4 
 drivers/usb/gadget/legacy/webcam.c  | 4 
 3 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uvc.c 
b/drivers/usb/gadget/function/f_uvc.c
index 54f04d321829..1d2feac5c532 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -31,6 +31,8 @@
 #include "uvc_video.h"
 
 unsigned int uvc_gadget_trace_param;
+module_param_named(trace, uvc_gadget_trace_param, uint, 0644);
+MODULE_PARM_DESC(trace, "Trace level bitmask");
 
 /* --
  * Function descriptors
diff --git a/drivers/usb/gadget/function/u_uvc.h 
b/drivers/usb/gadget/function/u_uvc.h
index a6fdde6b162b..2ed292e94fbc 100644
--- a/drivers/usb/gadget/function/u_uvc.h
+++ b/drivers/usb/gadget/function/u_uvc.h
@@ -21,7 +21,6 @@
 
 struct f_uvc_opts {
struct usb_function_instancefunc_inst;
-   unsigned intuvc_gadget_trace_param;
unsigned intstreaming_interval;
unsigned intstreaming_maxpacket;
unsigned intstreaming_maxburst;
@@ -81,7 +80,4 @@ struct f_uvc_opts {
int refcnt;
 };
 
-void uvc_set_trace_param(unsigned int trace);
-
 #endif /* U_UVC_H */
-
diff --git a/drivers/usb/gadget/legacy/webcam.c 
b/drivers/usb/gadget/legacy/webcam.c
index 6b86568c9157..a9f8eb8e1c76 100644
--- a/drivers/usb/gadget/legacy/webcam.c
+++ b/drivers/usb/gadget/legacy/webcam.c
@@ -30,9 +30,6 @@ static unsigned int streaming_maxburst;
 module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 
-static unsigned int trace;
-module_param(trace, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(trace, "Trace level bitmask");
 /* --
  * Device descriptor
  */
@@ -379,7 +376,6 @@ webcam_bind(struct usb_composite_dev *cdev)
uvc_opts->streaming_interval = streaming_interval;
uvc_opts->streaming_maxpacket = streaming_maxpacket;
uvc_opts->streaming_maxburst = streaming_maxburst;
-   uvc_set_trace_param(trace);
 
uvc_opts->fs_control = uvc_fs_control_cls;
    uvc_opts->ss_control = uvc_ss_control_cls;
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/3] usb: gadget: uvc: Minimize #include in headers

2018-05-21 Thread Laurent Pinchart
In order to speed up compilation, only include the headers that are
strictly required within other headers. To that end, use forward
structure declaration and move #include statements to .c file as
appropriate.

While at it, sort headers alphabetically, and remove unneeded __KERNEL__
guards.

Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/usb/gadget/function/f_uvc.c |  5 +++--
 drivers/usb/gadget/function/f_uvc.h |  6 +-
 drivers/usb/gadget/function/u_uvc.h |  1 +
 drivers/usb/gadget/function/uvc.h   | 14 ++
 drivers/usb/gadget/function/uvc_queue.h | 12 ++--
 drivers/usb/gadget/function/uvc_v4l2.c  |  3 ++-
 drivers/usb/gadget/function/uvc_video.h |  2 ++
 7 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uvc.c 
b/drivers/usb/gadget/function/f_uvc.c
index 439eba660e95..54f04d321829 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -6,16 +6,17 @@
  *     Laurent Pinchart (laurent.pinch...@ideasonboard.com)
  */
 
-#include 
-#include 
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/usb/gadget/function/f_uvc.h 
b/drivers/usb/gadget/function/f_uvc.h
index 81defe4557fe..a81a17765558 100644
--- a/drivers/usb/gadget/function/f_uvc.h
+++ b/drivers/usb/gadget/function/f_uvc.h
@@ -9,10 +9,7 @@
 #ifndef _F_UVC_H_
 #define _F_UVC_H_
 
-#include 
-#include 
-
-#include "uvc.h"
+struct uvc_device;
 
 void uvc_function_setup_continue(struct uvc_device *uvc);
 
@@ -21,4 +18,3 @@ void uvc_function_connect(struct uvc_device *uvc);
 void uvc_function_disconnect(struct uvc_device *uvc);
 
 #endif /* _F_UVC_H_ */
-
diff --git a/drivers/usb/gadget/function/u_uvc.h 
b/drivers/usb/gadget/function/u_uvc.h
index d00d3ded71c0..a6fdde6b162b 100644
--- a/drivers/usb/gadget/function/u_uvc.h
+++ b/drivers/usb/gadget/function/u_uvc.h
@@ -13,6 +13,7 @@
 #ifndef U_UVC_H
 #define U_UVC_H
 
+#include 
 #include 
 #include 
 
diff --git a/drivers/usb/gadget/function/uvc.h 
b/drivers/usb/gadget/function/uvc.h
index 053e4b72039d..93cf78b420fe 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -9,16 +9,22 @@
 #ifndef _UVC_GADGET_H_
 #define _UVC_GADGET_H_
 
-#include  /* For usb_endpoint_* */
+#include 
+#include 
+#include 
 #include 
-#include 
-#include 
 #include 
-#include 
+
 #include 
+#include 
+#include 
 
 #include "uvc_queue.h"
 
+struct usb_ep;
+struct usb_request;
+struct uvc_descriptor_header;
+
 /* 
  * Debugging, printing and logging
  */
diff --git a/drivers/usb/gadget/function/uvc_queue.h 
b/drivers/usb/gadget/function/uvc_queue.h
index f9f65b5c1062..2f0fff769843 100644
--- a/drivers/usb/gadget/function/uvc_queue.h
+++ b/drivers/usb/gadget/function/uvc_queue.h
@@ -2,13 +2,15 @@
 #ifndef _UVC_QUEUE_H_
 #define _UVC_QUEUE_H_
 
-#ifdef __KERNEL__
-
-#include 
+#include 
 #include 
-#include 
+#include 
+
 #include 
 
+struct file;
+struct mutex;
+
 /* Maximum frame size in bytes, for sanity checking. */
 #define UVC_MAX_FRAME_SIZE (16*1024*1024)
 /* Maximum number of video buffers. */
@@ -91,7 +93,5 @@ struct uvc_buffer *uvcg_queue_next_buffer(struct 
uvc_video_queue *queue,
 
 struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue);
 
-#endif /* __KERNEL__ */
-
 #endif /* _UVC_QUEUE_H_ */
 
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c 
b/drivers/usb/gadget/function/uvc_v4l2.c
index 9a9019625496..7f1ca3b57823 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -6,10 +6,11 @@
  * Laurent Pinchart (laurent.pinch...@ideasonboard.com)
  */
 
-#include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/usb/gadget/function/uvc_video.h 
b/drivers/usb/gadget/function/uvc_video.h
index 6c20aa75f966..7d77122b0ff9 100644
--- a/drivers/usb/gadget/function/uvc_video.h
+++ b/drivers/usb/gadget/function/uvc_video.h
@@ -12,6 +12,8 @@
 #ifndef __UVC_VIDEO_H__
 #define __UVC_VIDEO_H__
 
+struct uvc_video;
+
 int uvcg_video_pump(struct uvc_video *video);
 
 int uvcg_video_enable(struct uvc_video *video, int enable);
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] usb: gadget: uvc: Move userspace API definition to public header

2018-05-21 Thread Laurent Pinchart
The UVC gadget userspace API (V4L2 events and custom ioctls) is defined
in a header internal to the kernel. Move it to a new public header to
make it accessible to userspace.

The UVC_INTF_CONTROL and UVC_INTF_STREAMING macros are not used, so
remove them in the process.

Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 MAINTAINERS   |  1 +
 drivers/usb/gadget/function/uvc.h | 45 +--
 include/uapi/linux/usb/g_uvc.h| 39 +
 3 files changed, 45 insertions(+), 40 deletions(-)
 create mode 100644 include/uapi/linux/usb/g_uvc.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 58b9861ccf99..1ff4fa34febd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14772,6 +14772,7 @@ L:  linux-usb@vger.kernel.org
 S: Maintained
 F: drivers/usb/gadget/function/*uvc*
 F: drivers/usb/gadget/legacy/webcam.c
+F: include/uapi/linux/usb/g_uvc.h
 
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
 M: Jussi Kivilinna <jussi.kivili...@iki.fi>
diff --git a/drivers/usb/gadget/function/uvc.h 
b/drivers/usb/gadget/function/uvc.h
index a64e07e61f8c..053e4b72039d 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -9,52 +9,20 @@
 #ifndef _UVC_GADGET_H_
 #define _UVC_GADGET_H_
 
-#include 
-#include 
-#include 
-
-#define UVC_EVENT_FIRST(V4L2_EVENT_PRIVATE_START + 0)
-#define UVC_EVENT_CONNECT  (V4L2_EVENT_PRIVATE_START + 0)
-#define UVC_EVENT_DISCONNECT   (V4L2_EVENT_PRIVATE_START + 1)
-#define UVC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2)
-#define UVC_EVENT_STREAMOFF(V4L2_EVENT_PRIVATE_START + 3)
-#define UVC_EVENT_SETUP(V4L2_EVENT_PRIVATE_START + 4)
-#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
-#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
-
-struct uvc_request_data {
-   __s32 length;
-   __u8 data[60];
-};
-
-struct uvc_event {
-   union {
-   enum usb_device_speed speed;
-   struct usb_ctrlrequest req;
-   struct uvc_request_data data;
-   };
-};
-
-#define UVCIOC_SEND_RESPONSE   _IOW('U', 1, struct uvc_request_data)
-
-#define UVC_INTF_CONTROL   0
-#define UVC_INTF_STREAMING 1
-
-/* 
- * Debugging, printing and logging
- */
-
-#ifdef __KERNEL__
-
 #include  /* For usb_endpoint_* */
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
 #include "uvc_queue.h"
 
+/* 
+ * Debugging, printing and logging
+ */
+
 #define UVC_TRACE_PROBE(1 << 0)
 #define UVC_TRACE_DESCR(1 << 1)
 #define UVC_TRACE_CONTROL  (1 << 2)
@@ -184,7 +152,4 @@ extern void uvc_endpoint_stream(struct uvc_device *dev);
 extern void uvc_function_connect(struct uvc_device *uvc);
 extern void uvc_function_disconnect(struct uvc_device *uvc);
 
-#endif /* __KERNEL__ */
-
 #endif /* _UVC_GADGET_H_ */
-
diff --git a/include/uapi/linux/usb/g_uvc.h b/include/uapi/linux/usb/g_uvc.h
new file mode 100644
index ..3c9ee3020cbb
--- /dev/null
+++ b/include/uapi/linux/usb/g_uvc.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * g_uvc.h  --  USB Video Class Gadget driver API
+ *
+ * Copyright (C) 2009-2010 Laurent Pinchart <laurent.pinch...@ideasonboard.com>
+ */
+
+#ifndef __LINUX_USB_G_UVC_H
+#define __LINUX_USB_G_UVC_H
+
+#include 
+#include 
+#include 
+
+#define UVC_EVENT_FIRST(V4L2_EVENT_PRIVATE_START + 0)
+#define UVC_EVENT_CONNECT  (V4L2_EVENT_PRIVATE_START + 0)
+#define UVC_EVENT_DISCONNECT   (V4L2_EVENT_PRIVATE_START + 1)
+#define UVC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2)
+#define UVC_EVENT_STREAMOFF(V4L2_EVENT_PRIVATE_START + 3)
+#define UVC_EVENT_SETUP(V4L2_EVENT_PRIVATE_START + 4)
+#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
+#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
+
+struct uvc_request_data {
+   __s32 length;
+   __u8 data[60];
+};
+
+struct uvc_event {
+   union {
+   enum usb_device_speed speed;
+   struct usb_ctrlrequest req;
+   struct uvc_request_data data;
+   };
+};
+
+#define UVCIOC_SEND_RESPONSE   _IOW('U', 1, struct uvc_request_data)
+
+#endif /* __LINUX_USB_G_UVC_H */
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/3] usb: gadget: uvc: Expose UAPI & miscellaneous cleanups

2018-05-21 Thread Laurent Pinchart
Hello,

Here are a few miscellaneous patches prompted by drive-by fixes.

The first patch moves the definition of the UVC function userspace API
to a public header in include/uapi/ for consumption by userspace. This
should remove the need to manually copy the file when compiling
userspace applications, or, worse, to use relative include paths that
point within the kernel source tree.

The next two patches are small cleanups for miscellaneous things that
bothered me while writing the first patch. There isn't much of a design
to comment on, please see individual patches for details.

Laurent Pinchart (3):
  usb: gadget: uvc: Move userspace API definition to public header
  usb: gadget: uvc: Minimize #include in headers
  usb: gadget: uvc: Move trace parameter to function module

 MAINTAINERS |  1 +
 drivers/usb/gadget/function/f_uvc.c |  7 +++--
 drivers/usb/gadget/function/f_uvc.h |  6 +---
 drivers/usb/gadget/function/u_uvc.h |  5 +---
 drivers/usb/gadget/function/uvc.h   | 53 -
 drivers/usb/gadget/function/uvc_queue.h | 12 
 drivers/usb/gadget/function/uvc_v4l2.c  |  3 +-
 drivers/usb/gadget/function/uvc_video.h |  2 ++
 drivers/usb/gadget/legacy/webcam.c  |  4 ---
 include/uapi/linux/usb/g_uvc.h  | 39 
 10 files changed, 69 insertions(+), 63 deletions(-)
 create mode 100644 include/uapi/linux/usb/g_uvc.h

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Some questions about the UVC gadget

2018-05-21 Thread Laurent Pinchart
Hello Kelly,

Sorry for the late reply, your e-mail got buried in my inbox :-/

On Friday, 23 February 2018 05:36:55 EEST Kelly Huang wrote:
> Dear Mr.Pinchart,
> 
> > I'm afraid the Linux UVC gadget driver doesn't support H.264. While H.264
> > support could be implemented using UVC 1.1, I wouldn't recommend this as
> > the UVC 1.1 H.264 specification is a hack that is not and will not be
> > supported in the Linux UVC host driver. UVC 1.5 is the way to go for
> > H.264.
> 
> I have a  Logitech C920 usb camera which claims H.264 support. When I used
> it under my usb protocol analyzer, I found that one of the CS_INTERFACE
> descriptor had a VS_FORMAT_FRAME_BASED subtype, and the guidFormat is
> '48323634-1000-80AA-389B71', including the 'H264' symbols.
> 
> I don't know if that is the way you talked about implementing H.264 using
> UVC 1.1? It seems that I need to rename some descriptors of the UVC gadget
> driver and write a userspace application to fill /dev/videoX with H.264
> streams. If so, can it work correctly?

I spoke a bit too fast in my previous e-mail. H.264 support with UVC 1.1 
should be OK, as long as you don't use the H.264 UVC 1.1 stream multiplexing 
method that allows transmitting multiple video streams over a single endpoint.

The support H.264 with UVC 1.1 you will need to create the corresponding 
descriptors, and to implement support in the userspace helper application for 
the H.264 extension unit (XU) defined in the UVC 1.1 specification.

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/3] usb: gadget: uvc: fix racing between uvc_function_set_alt and streamon/off

2018-05-21 Thread Laurent Pinchart
Hi Paul,

On Tuesday, 24 April 2018 23:59:33 EEST Paul Elder wrote:
> Down the call stack from the ioctl handler for VIDIOC_STREAMON,
> uvc_video_alloc_requests contains a BUG_ON, which in the high level,
> triggers when VIDIOC_STREAMON ioctl is issued without VIDIOC_STREAMOFF
> being issued previously.
> 
> This can happen in a few ways, such as if the userspace uvc gadget
> application simply doesn't issue VIDIOC_STREAMOFF. Another way is if
> uvc_function_set_alt with alt 0 is called after it is called with 1 but
> before VIDIOC_STREAMON is called; in this case, UVC_EVENT_STREAMOFF will
> not be queued to userspace, and therefore userspace will never call
> VIDIOC_STREAMOFF.
> 
> To fix this, add two more uvc states: starting and stopping. The
> starting state is entered when uvc_function_set_alt 1 is called, and is
> exited in uvc_v4l2_streamon, when the state is changed to streaming. The
> stopping state is entered when uvc_function_set_alt 0 is called, and is
> exited in uvc_v4l2_streamoff, when the state is changed to connected.

It would be useful to capture this in kerneldoc as a documentation of the 
states enum. I believe writing the description of state transitions down will 
also help you understand the potential race conditions.

> The status phase of the SET_INTERFACE request doesn't need to be delayed
> by the uvc gadget driver, so that is removed.
> 
> Finally, there is another way to trigger the aforementioned BUG: start
> streaming and (physically) disconnect usb. To fix this, call
> uvcg_video_enable 0 in uvc_function_disable.
> 
> Changes in v2:
>   1. Remove delay usb status phase
> 
> Paul Elder (3):
>   usb: gadget: uvc: synchronize streamon/off with uvc_function_set_alt
>   usb: gadget: uvc: remove delay usb status phase from uvc
>   usb: gadget: uvc: disable stream when disconnected
> 
>  drivers/usb/gadget/function/f_uvc.c| 14 +++---
>  drivers/usb/gadget/function/uvc.h  |  2 ++
>  drivers/usb/gadget/function/uvc_v4l2.c | 21 +++--
>  3 files changed, 28 insertions(+), 9 deletions(-)

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 3/3] usb: gadget: uvc: disable stream when disconnected

2018-05-21 Thread Laurent Pinchart
Hi Paul,

Thank you for the patch.

On Tuesday, 24 April 2018 23:59:36 EEST Paul Elder wrote:
> Down the call stack from the ioctl handler for VIDIOC_STREAMON,
> uvc_video_alloc_requests contains a BUG_ON, which in the high level,
> triggers when VIDIOC_STREAMON ioctl is issued without VIDIOC_STREAMOFF
> being issued previously.
> 
> This can also be triggered by starting the stream and then physically
> disconnecting usb. To fix this, do the streamoff procedures on usb
> disconnect.
> 
> Signed-off-by: Paul Elder <paul.el...@ideasonboard.com>
> ---
> Changes in v2: Nothing
> 
>  drivers/usb/gadget/function/f_uvc.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/usb/gadget/function/f_uvc.c
> b/drivers/usb/gadget/function/f_uvc.c index fa34dcbe1197..5bb79888e3f7
> 100644
> --- a/drivers/usb/gadget/function/f_uvc.c
> +++ b/drivers/usb/gadget/function/f_uvc.c
> @@ -374,9 +374,12 @@ uvc_function_disable(struct usb_function *f)
>  {
>   struct uvc_device *uvc = to_uvc(f);
>   struct v4l2_event v4l2_event;
> + struct uvc_video *video = >video;
> 
>   INFO(f->config->cdev, "uvc_function_disable\n");
> 
> + uvcg_video_enable(video, 0);
> +

As commented in my reply to patch 2/3, you will need to protect this with 
proper locking. You now have at least four events dealing with states and 
buffers allocation (VIDIOC_STREAMON, VIDIOC_STREAMOFF, uvc_function_set_alt 
and uvc_function_disable).

>   memset(_event, 0, sizeof(v4l2_event));
>   v4l2_event.type = UVC_EVENT_DISCONNECT;
>   v4l2_event_queue(>vdev, _event);

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/3] usb: gadget: uvc: synchronize streamon/off with uvc_function_set_alt

2018-05-21 Thread Laurent Pinchart
uvc->state != UVC_STATE_STOPPING)
> + return 0;

Same comment here, this should go after the next check.

While I think extending the state machine this way makes sense, I believe 
you're introducing race conditions. The VIDIOC_STREAMON and VIDIOC_STREAMOFF 
ioctls can be issued by userspace at any time, completely asynchronously to 
the reception of SET_INTERFACE requests. You will need a lock to protect this. 
I recommend trying to draw sequence diagrams to see how the different events 
can race each other.

>   if (type != video->queue.queue.type)
>   return -EINVAL;
> 
> - return uvcg_video_enable(video, 0);
> + ret = uvcg_video_enable(video, 0);
> + if (ret < 0)
> + return ret;
> +
> + uvc->state = UVC_STATE_CONNECTED;
> +
> + return 0;
> +
>  }
> 
>  static int

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/3] usb: gadget: uvc: remove delay usb status phase

2018-05-21 Thread Laurent Pinchart
Hi Paul,

Thank you for the patch.

On Tuesday, 24 April 2018 23:59:35 EEST Paul Elder wrote:
> The completion of the usb status phase doesn't need to be delayed
> from uvc_function_set_alt to uvc_v4l2_streamon/off.
> Remove USB_GADGET_DELAYED_STATUS and usb_composite_setup_delay from
> these two, respectively.

Did you mean uvc_function_setup_continue() ?

In addition to Roger's comment regarding the uvc_function_setup_continue() 
function that can now be removed (don't forget the header files), I think the 
commit message would benefit from more details. How about the following ?

usb: gadget: uvc: Don't delay the status phase of SET_INTERFACE requests

Reception of a SET_INTERFACE request with a non-zero alternate setting
signals the start of the video stream. The gadget has to enable the
video streaming endpoint and to signal stream start to userspace, in
order to start receiving video frames to transmit over USB. As userspace
can be slow to react, the UVC function driver delays the status phase of
the SET_INTERFACE control transfer until userspace is ready.

The status phase is delayed by returning USB_GADGET_DELAYED_STATUS from
the function's .set_alt() handler. This creates a race condition as the
userspace application could process the stream start event before the
composite layer processes the USB_GADGET_DELAYED_STATUS return value.
The race has been observed in practice, and can't be solved without a
change to the USB_GADGET_DELAYED_STATUS API.

Fortunately the UVC function driver doesn't strictly require delaying
the status phase, as the only requirement from a USB point of view is
that the streaming endpoint must be enabled before the status phase
completes, and that is already guaranteed by the current code. We can
thus complete the status phase synchronously, removing the race
condition at the same time.

Without delaying the status phase the host will likely start issuing
isochronous transfers before we queue the first USB requests. The UDC
will reply with NAKs which should be handled properly by the host. If
this ends up causing issues another option will be to modify the status
phase delay API to fix the race condition.

> Signed-off-by: Paul Elder <paul.el...@ideasonboard.com>
> ---
> Changes in v2:
>   1. Remove delay usb status phase
> 
>  drivers/usb/gadget/function/f_uvc.c| 3 ++-
>  drivers/usb/gadget/function/uvc_v4l2.c | 6 --
>  2 files changed, 2 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/usb/gadget/function/f_uvc.c
> b/drivers/usb/gadget/function/f_uvc.c index 9b63b28a1ee3..fa34dcbe1197
> 100644
> --- a/drivers/usb/gadget/function/f_uvc.c
> +++ b/drivers/usb/gadget/function/f_uvc.c
> @@ -361,7 +361,8 @@ uvc_function_set_alt(struct usb_function *f, unsigned
> interface, unsigned alt) memset(_event, 0, sizeof(v4l2_event));
>   v4l2_event.type = UVC_EVENT_STREAMON;
>   v4l2_event_queue(>vdev, _event);
> - return USB_GADGET_DELAYED_STATUS;
> +
> + return 0;
> 
>   default:
>   return -EINVAL;
> diff --git a/drivers/usb/gadget/function/uvc_v4l2.c
> b/drivers/usb/gadget/function/uvc_v4l2.c index fdf02b6987c0..138d95b3b8d1
> 100644
> --- a/drivers/usb/gadget/function/uvc_v4l2.c
> +++ b/drivers/usb/gadget/function/uvc_v4l2.c
> @@ -206,12 +206,6 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum
> v4l2_buf_type type)
> 
>   uvc->state = UVC_STATE_STREAMING;
> 
> - /*
> -  * Complete the alternate setting selection setup phase now that
> -  * userspace is ready to provide video frames.
> -  */
> - uvc_function_setup_continue(uvc);
> -
>   return 0;
>  }

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Pandaboard OMAP4 MUSB short packet hang on UVC gadget

2018-05-18 Thread Laurent Pinchart
Hi Bin,

On Wednesday, 16 May 2018 18:45:40 EEST Bin Liu wrote:
> On Tue, May 15, 2018 at 10:58:16PM +0100, Kieran Bingham wrote:
> > Hi Bin, Felipe,
> > 
> > We have been trying to get a UVC gadget operational on the Pandaboard ES
> > platform, and we believe we've hit an issue with short packets on the MUSB
> > in DMA mode.
> 
> I don't have a Pandaboard. Does it use MUSB internal DMA engine?

It uses the OMAP2+ glue and the Inventra DMA engine, yes.

> > Using the g_webcam module, I can instantiate a UVC video node, and use the
> > uvc-gadget helper application [0] to handle the frame generation.
> > 
> > With DMA disabled using CONFIG_MUSB_PIO_ONLY I am able to process frames
> > on the host using yavta [1]
> > 
> > However when DMA is enabled, only the first frame is transmitted to the
> > host, and I get an error from the musb_log debug prints which indicate
> > that the MUSB_TXCSR_TXPKTRDY is not cleared following a short packet.
> 
> The MUSB_TXCSR_TXPKTRDY bit should be clear by the MUSB controller after
> the TX packet is transmitted, there is no sw involved.

I've just found 
https://groups.google.com/forum/?hl=en#!topic/beagleboard-gsoc/k8Azwfp75CU that 
seems to be related. We'll try it out. Does the patch 
make sense to you ?

> > A capture of the musb_log trace-points [2] shows the following at the end
> > of the log:
> > 
> > The 'mode' has been set to '0' instead of '1', buffer length is 902
> > instead of 1024 (expected behaviour for the last packet):
> >   "ep13-Tx pkt_sz 1024, dma_addr 0xadfbbc00 length 902, mode 0"
> > 
> > And then there is a fault reported:
> >   "ep13 old packet still ready , txcsr 2003"
> 
> I just checked the same testcase on Beaglebone Black which uses CPPI41
> DMA, this bit is cleared after sent the 902-bytes end-of-frame packet.

That would point to an issue with the Inventra DMA engine, which would be 
consistent with the above patch.

> > The host (linux, running the uvc driver with extra debug prints) reports:
> > 
> > [24517.711147] uvcvideo: decode_data: len: 1022, maxlen 460800
> > [24517.759117] uvcvideo: decode_data: len: 1022, maxlen 459778
> >  ...
> > [24529.375018] uvcvideo: decode_data: len: 1022, maxlen 2944
> > [24529.399073] uvcvideo: decode_data: len: 1022, maxlen 1922
> > [24529.427014] uvcvideo: decode_data: len: 900, maxlen 900
> > 
> > And receives no further data following the end of the first frame.
> > 
> > 
> > Are there any known issues on the musb-gadget with short-packet handling -
> > or any other tests I can perform to check this ?
> 
> Nothing that I am aware of.
> 
> > Should I be looking to try to get the txstate() call to re-execute after a
> > delay (using musb_queue_resume_work() perhaps?) or does this indicate
> > that the
> 
> I am not sure how that will make the controller to clear the TXPKTRDY
> bit.
> 
> > hardware has jammed ? Stopping the pipeline (the yavta capture) and
> > restarting,
> 
> Likely that is the case.
> 
> > will successfully transfer (only) the first frame again.
> > 
> > Any other hints and tips appreciated!
> 
> Does the usecase ever worked on Pandaboard with older kernels? If so,
> you can try to bisect the commit which causes the regression.

Not that I recall. The use case was initially developed on a Davinci system, 
and has been tested on a Beagleboard, but I don't remember having tested it on 
OMAP4.

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/4] usb: gadget: composite: add function to increment delayed_status

2018-04-21 Thread Laurent Pinchart
Hi Alan,

On Friday, 20 April 2018 17:09:57 EEST Alan Stern wrote:
> On Thu, 19 Apr 2018, Laurent Pinchart wrote:
> > According to include/linux/usb/composite.h, the delayed_status field
> > should be protected by cdev->lock, which you should use here.
> > 
> > I've read through the code and found out that, while all callers of
> > reset_config(), as well as usb_composite_setup_continue(), correctly take
> > the lock, it isn't taken around f->set_alt() in composite_setup(). This
> > causes the race condition. I wonder if a simpler fix wouldn't be to take
> > the lock before calling f->set_alt() and releasing it after incrementing
> > delayed_status. I am however worried that this could lead to deadlocks if
> > one of the existing set_alt() handlers calls a function that takes the
> > same lock. Another worry is that some of the .set_alt() handlers might
> > not expect to be called with interrupts disabled. This should be
> > analyzed, and I hope that Roger and/or Felipe will have some insight on
> > this.
> 
> set_alt handlers generally have to disable and enable endpoints, which
> requires a process context.  They cannot run with interrupts disabled.

Thank you for the information. Isn't the following code path problematic then 
?

int
composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
{
...
case USB_REQ_SET_CONFIGURATION:
...
spin_lock(>lock);
value = set_config(cdev, ctrl, w_value);
spin_unlock(>lock);
...
}

static int set_config(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl, unsigned number)
{
...
/* Initialize all interfaces by setting them to altsetting zero. */
for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
...
result = f->set_alt(f, tmp, 0);
...
}

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/4] usb: gadget: composite: add function to increment delayed_status

2018-04-19 Thread Laurent Pinchart
Hi Paul,

(CC'ing Felipe Balbi and Roger Quadros)

Thank you for the patch.

Have you used scripts/get_maintainer.pl ? It should point you to Felipe Balbi, 
the maintainer of the USB gadget subsystem, who I recommend you CC, at least 
on patch 2/4. The script also points to Greg, who I don't think needs to be 
CC'ed as he doesn't deal with USB gadget as much as with USB in general, and 
who is fairly busy as usual.

While the get_maintainer script doesn't point to Roger, his name can be found 
as the author of the USB_GADGET_DELAYED_STATUS mechanism. He authored commit 
1b9ba000177e ("usb: gadget: composite: Allow function drivers to pause control 
transfers") with his nokia.com address back then, but git log --author 'Roger 
Quadros' shows that he's still active on USB and working for TI now. I've thus 
CC'ed him on this reply.

On Wednesday, 18 April 2018 06:18:14 EEST Paul Elder wrote:
> The completion of the usb status phase from uvc_function_set_alt needs
> to be delayed until uvc_v4l2_streamon/off. This is currently done by
> uvc_function_set_alt returning USB_GADGET_DELAYED_STATUS and
> composite_setup detecting this to increment cdev->delayed_status.
> However, if uvc_v4l2_streamon/off is called in between this return and
> increment, uvc_function_setup_continue within uvc_v4l2_streamon/off will
> WARN that cdev->delayed_status is zero.

While this is correct, I wouldn't mention UVC here as the patch is for the USB 
composite gadget framework and isn't specific to UVC. You should write a more 
generic explanation of the problem to explain why the race between returning 
USB_GADGET_DELAYED_STATUS (and processing it in the caller) and calling 
usb_composite_setup_continue() can't be properly solved in gadget drivers, 
thus requiring a new function.

> To fix situations like this, add a function to increment
> cdev->delayed_status.
> 
> Signed-off-by: Paul Elder <paul.el...@pitt.edu>
> ---
>  drivers/usb/gadget/composite.c | 6 ++
>  include/linux/usb/composite.h  | 2 ++
>  2 files changed, 8 insertions(+)
> 
> diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
> index 77c7ecca816a..c02ab640a7ae 100644
> --- a/drivers/usb/gadget/composite.c
> +++ b/drivers/usb/gadget/composite.c
> @@ -1548,6 +1548,12 @@ static int fill_ext_prop(struct usb_configuration *c,
> int interface, u8 *buf) return 0;
>  }
> 
> +void usb_composite_setup_delay(struct usb_composite_dev *cdev)
> +{
> + cdev->delayed_status++;

According to include/linux/usb/composite.h, the delayed_status field should be 
protected by cdev->lock, which you should use here.

I've read through the code and found out that, while all callers of 
reset_config(), as well as usb_composite_setup_continue(), correctly take the 
lock, it isn't taken around f->set_alt() in composite_setup(). This causes the 
race condition. I wonder if a simpler fix wouldn't be to take the lock before 
calling f->set_alt() and releasing it after incrementing delayed_status. I am 
however worried that this could lead to deadlocks if one of the existing 
set_alt() handlers calls a function that takes the same lock. Another worry 
is that some of the .set_alt() handlers might not expect to be called with 
interrupts disabled. This should be analyzed, and I hope that Roger and/or 
Felipe will have some insight on this.

If usb_composite_setup_delay() turns out to be the preferred solution, it 
would be nice to document the function with kerneldoc.

Finally, I just came to wonder whether the UVC gadget driver really needs to 
defer the status phase of the SET_INTERFACE request, or if it couldn't just 
proceed normally.

> +}
> +EXPORT_SYMBOL(usb_composite_setup_delay);
> +
>  /*
>   * The setup() callback implements all the ep0 functionality that's
>   * not handled lower down, in hardware or the hardware driver(like
> diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
> index cef0e44601f8..049f77a4d42b 100644
> --- a/include/linux/usb/composite.h
> +++ b/include/linux/usb/composite.h
> @@ -524,6 +524,8 @@ extern int composite_setup(struct usb_gadget *gadget,
>  extern void composite_suspend(struct usb_gadget *gadget);
>  extern void composite_resume(struct usb_gadget *gadget);
> 
> +extern void usb_composite_setup_delay(struct usb_composite_dev *c);
> +
>  /*
>   * Some systems will need runtime overrides for the  product identifiers
>   * published in the device descriptor, either numbers or strings or both.

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/5] usb: gadget: uvc: fix racing between uvc_function_set_alt and streamon/off

2018-04-19 Thread Laurent Pinchart
Hi Paul,

Thank you for the patch series. I believe you've already noticed that the 
subject line of the cover letter should have mentioned 0/4 instead of 0/5.

On Wednesday, 18 April 2018 06:20:15 EEST Paul Elder wrote:
> Down the call stack from the ioctl handler for VIDIOC_STREAMON,
> uvc_video_alloc_requests contains a BUG_ON, which in the high level,
> triggers when VIDIOC_STREAMON ioctl is issued without VIDIOC_STREAMOFF
> being issued previously.
> 
> This can happen in a few ways, such as if the userspace uvc gadget
> application simply doesn't issue VIDIOC_STREAMOFF. Another way is if
> uvc_function_set_alt with alt 0 is called after it is called with 1 but
> before VIDIOC_STREAMON is called; in this case, UVC_EVENT_STREAMON will

I assume you meant UVC_EVENT_STREAMOFF here.

> not be queued to userspace, and therefore userspace will never call
> VIDIOC_STREAMOFF.
> 
> To fix this, add two more uvc states: starting and stopping. The
> starting state starts when uvc_function_set_alt 1 is called, and ends
> in uvc_v4l2_streamon, when the state is changed to streaming.

Nitpicking, as we're talking about states, I would say "is entered" instead of 
"starts" and "is exited" instead of "ends".

> The stopping state starts when uvc_function_set_alt 0 is called, and ends
> in uvc_v4l2_streamoff, when the state is changed to connected.
> 
> Along with this fix, the completion of the usb status phase needs to be
> delayed until uvc_v4l2_streamon/off. This is already the case for
> uvc_function_set_alt 1, so add this to when alt is 0. However, the
> delayed_status is only incremented when this function returns, so if
> uvc_v4l2_streamon/off is called in between returning and incrementing,
> then uvc_function_setup_continue will WARN that delayed_status is zero.
> 
> To fix this, add and use usb_composite_setup_delay,
> which increments the delayed_status. Then, uvc_function_set_alt
> returns 0 instead of USB_GADGET_DELAYED_STATUS.
> 
> Finally, there is another way to trigger the aforementioned BUG: start
> streaming and (physically) disconnect usb. To fix this, call
> uvcg_video_enable 0 in uvc_function_disable.

This is a clear and detailed cover letter, good job ! I'll review the 
individual patches now.

> Paul Elder (4):
>   usb: gadget: uvc: synchronize streamon/off with uvc_function_set_alt
>   usb: gadget: composite: add function to increment delayed_status
>   usb: gadget: uvc: synchronize usb status phase delay for
> uvc_function_set_alt
>   usb: gadget: uvc: disable stream when disconnected
> 
>  drivers/usb/gadget/composite.c |  6 ++
>  drivers/usb/gadget/function/f_uvc.c| 24 +---
>  drivers/usb/gadget/function/uvc.h  |  2 ++
>  drivers/usb/gadget/function/uvc_v4l2.c | 21 +++--
>  include/linux/usb/composite.h  |  2 ++
>  5 files changed, 50 insertions(+), 5 deletions(-)

-- 
Regards,

Laurent Pinchart



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb/gadget/uvc-configs Fix host unable to negotiate framesizes other than first

2018-03-21 Thread Laurent Pinchart
Hi Joel,

On Wednesday, 21 March 2018 11:53:45 EET Joel Pepper wrote:
> Hi Laurent,
> 
> Thanks for the heads up. I noticed the goof with Patch v3 right after
> sending, but apparently I screwed up the commit amend too. I'm still
> getting accustomed to kernel development. Sorry for wasting your time, I
> will have v4 along shortly

If the result is that you become more familiar with kernel development and 
keep contributing I'll consider this as time well invested, not wasted.

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb/gadget/uvc-configs Fix host unable to negotiate framesizes other than first

2018-03-21 Thread Laurent Pinchart
Hi Joel,

Thank you for the patch.

On Tuesday, 20 March 2018 22:28:53 EET Joel Pepper wrote:
> - Add bFrameIndex as a UVCG_FRAME_ATTR_RO for each frame size.
> - Automatically assign ascending bFrameIndex to each frame in a format.
> 
> Before all "bFrameindex" attributes were set to "1" with no way to
> configure the gadget otherwise. This resulted in the host always
> negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
> After the negotiation the host driver will set the user or application
> selected framesize, while the gadget is actually set to the first
> framesize.
> 
> Now, when the containing format is linked into the streaming header,
> iterate over all child frame descriptors and assign ascending indices.
> The automatically assigned indices can be read from the new read only
> bFrameIndex configsfs attribute in each frame descriptor item.
> 
> v2: Add the new attribute to both MJPEG and uncompressed frame descriptors
> in Documentation/ABI, with note that it was added only in a later
> kernel version
> 
> v3: Changed from simply allowing user to set the value for bFrameIndex to
> automatically assigning correct distinct frame indexes. Changed
> bFrameIndex from RW to RO

I like the new commit message, but it would be nice if you could also update 
the patch contents ;-)

(By the way the subject line should have mentioned "[PATCH v3]")

> Signed-off-by: Joel Pepper <joel.pep...@rwth-aachen.de>
> ---
>  Documentation/ABI/testing/configfs-usb-gadget-uvc | 17 +
>  drivers/usb/gadget/function/uvc_configfs.c|  3 +++
>  2 files changed, 20 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc
> b/Documentation/ABI/testing/configfs-usb-gadget-uvc index 1ba0d0f..d435cf7
> 100644
> --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
> +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
> @@ -194,6 +194,14 @@ Description: Specific MJPEG frame descriptors
>   bmCapabilities  - still image support, fixed frame-rate
>   support
> 
> +Date:Mar 2018
> +KernelVersion:   4.16
> +
> + bFrameIndex - unique id for this framedescriptor;
> + if using multiple framedescriptors for
> + same format, user needs to set distinct
> + value for each frame descriptor
> +
>  What:/config/usb-gadget/gadget/functions/uvc.name/streaming/
uncompressed
>  Date:Dec 2014
>  KernelVersion:   4.0
> @@ -241,6 +249,15 @@ Description: Specific uncompressed frame descriptors
>   bmCapabilities  - still image support, fixed frame-rate
>   support
> 
> +Date:   Mar 2018
> +KernelVersion:  4.16
> +
> +bFrameIndex - unique id for this
> framedescriptor; +if using multiple
> framedescriptors for +same format,
> user needs to set distinct +value
> for each frame descriptor +
> +
>  What:
> /config/usb-gadget/gadget/functions/uvc.name/streaming/header
>  Date:Dec 2014
>  KernelVersion:   4.0
> diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> b/drivers/usb/gadget/function/uvc_configfs.c index c9b8cc4a..5966d65 100644
> --- a/drivers/usb/gadget/function/uvc_configfs.c
> +++ b/drivers/usb/gadget/function/uvc_configfs.c
> @@ -992,6 +992,8 @@ UVC_ATTR(uvcg_frame_, cname, aname);
> 
>  UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
>   noop_conversion, 8);
> +UVCG_FRAME_ATTR(b_frame_index, bFrameIndex, noop_conversion,
> + noop_conversion, 8);
>  UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
>  UVCG_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16);
>  UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32,
> 32); @@ -1137,6 +1139,7 @@ UVC_ATTR(uvcg_frame_, dw_frame_interval,
> dwFrameInterval);
> 
>  static struct configfs_attribute *uvcg_frame_attrs[] = {
>   _frame_attr_bm_capabilities,
> + _frame_attr_b_frame_index,
>   _frame_attr_w_width,
>   _frame_attr_w_height,
>   _frame_attr_dw_min_bit_rate,

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2] usb/gadget/uvc-configs Fix host unable to negotiate framesizes other than first

2018-03-21 Thread Laurent Pinchart
Hi Joel,

On Tuesday, 20 March 2018 12:30:00 EET Joel Pepper wrote:
> On 20.03.2018 10:02, Laurent Pinchart wrote:
> > Hi Joel,
> > 
> > (CC'ing Paul Elder who is working on the UVC gadget driver)
> > 
> > Thank you for the patch.
> > 
> > On Monday, 19 March 2018 21:36:41 EET Joel Pepper wrote:
> >> Add bFrameIndex as a UVCG_FRAME_ATTR for each frame size.
> >> Before all "bFrameindex" attributes were set to "1" with no way to
> >> configure the gadget otherwise. This resulted in the host always
> >> negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
> >> After the negotiation the host driver will set the user or application
> >> selected framesize, while the gadget is actually set to the first
> >> framesize.
> >> 
> >> Note that this still requires the gadget to be configured with unique
> >> bFrameIndexes for each frameSize of each format through configfs. An
> >> alternative might be to automatically assign ascending indices when the
> >> format is linked into the streaming header, but the user space gadget
> >> would need a way to check or predict the indices so that it can properly
> >> interpret to PROBE/COMMIT CONTROL requests
> > 
> > It would indeed be nice if the indices could be automatically generated,
> > to avoid giving userspace another possibility to create invalid
> > descriptors. As you've correctly noted, that would require a way for the
> > userspace helper application to coordinate with the UVC gadget driver.
> > Would it be difficult to do so by defining the bFrameIndex attribute as
> > read-only ? There's the additional issue of finding a place to store the
> > index counter locally to the format, I'm not sure how that's done with the
> > configfs API, but if it's not too difficult I think it would be a good
> > option.
> 
> Setting bFrameIndex to be read-only will suffice in allowing the
> userspace gadget to coordinate with the driver at the (slight) expense of
> the userspace gadget not being able to dictate an order which is
> semantically meaningful to it.
> 
> There are two approaches I see towards assigning indices automatically:
> 1) Assign a new unique index in "uvcg_frame_make" (i.e. config item
> creation)
> 2) Assign indices when exact set of frame descriptors is finalized (i.e.
> linking into the streaming header)
> 
> As for 1):
> I think this is the approach you are referring to with regards to
> storing the index counter in the format. There already is a 'num_frames'
> unsigned int in the uvcg_format struct, which could be used as index,
> however this approach does not handle deleting frame descriptors well,
> because num_frames is decremented then. Unless frames are always deleted in
> reverse order of creation this will produce index collisions. If we instead
> use a new monotonously incrementing counter, deleting frames will produce
> "holes" in the indices (I think UVC does allow for that but it might trip
> up host drivers not expecting that). The counter would also overflow after
> creating 255 frames even if the final number is much lower.
> 
> 
> As for 2):
> I personally prefer this approach as it avoids the problems of 1). It
> depends on identifying a point in time when the set of frame descriptors
> cannot change anymore I think this is given when the format is linked into
> the streaming header. It should then suffice to iterate of the contained
> frames and assign ascending indices. A small problem however is that the
> attribute will have no meaningful value to be read before the format is
> linked. This fact will need to be communicated in the documentation and
> potentially through returning EBUSY on premature read attempts.
> 
> I'll prepare a patch implementing 2), but in the meantime I'm grateful
> for more input, as there is not necessarily a single best approach to be
> taken here.

I like the second approach for the reasons you've described above.

Returning -EBUSY might not even be necessary, as before the gadget is fully 
setup there will be no V4L2 device registered anyway, and the userspace helper 
application will thus not be able to proceed. It however seems a good idea to 
let userspace know that the attribute isn't ready yet, so I agree with your 
proposal.

> >> v2: Add the new attribute to both MJPEG and uncompressedframe descriptos
> >> in Documentation/ABI, with note that it was added only in a later
> >> kernel version
> >> 
> >> Signed-off-by: Joel Pepper <joel.pep...@rwth-aachen.de>
> >> ---
> >> 
> >>  Documentation/ABI/testing/configfs-usb-gadget

Re: [PATCHv2] usb/gadget/uvc-configs Fix host unable to negotiate framesizes other than first

2018-03-20 Thread Laurent Pinchart
Hi Joel,

(CC'ing Paul Elder who is working on the UVC gadget driver)

Thank you for the patch.

On Monday, 19 March 2018 21:36:41 EET Joel Pepper wrote:
> Add bFrameIndex as a UVCG_FRAME_ATTR for each frame size.
> Before all "bFrameindex" attributes were set to "1" with no way to
> configure the gadget otherwise. This resulted in the host always
> negotiating for bFrameIndex 1 (i.e. the first framesize of the gadget).
> After the negotiation the host driver will set the user or application
> selected framesize, while the gadget is actually set to the first
> framesize.
> 
> Note that this still requires the gadget to be configured with unique
> bFrameIndexes for each frameSize of each format through configfs. An
> alternative might be to automatically assign ascending indices when the
> format is linked into the streaming header, but the user space gadget
> would need a way to check or predict the indices so that it can properly
> interpret to PROBE/COMMIT CONTROL requests

It would indeed be nice if the indices could be automatically generated, to 
avoid giving userspace another possibility to create invalid descriptors. As 
you've correctly noted, that would require a way for the userspace helper 
application to coordinate with the UVC gadget driver. Would it be difficult to 
do so by defining the bFrameIndex attribute as read-only ? There's the 
additional issue of finding a place to store the index counter locally to the 
format, I'm not sure how that's done with the configfs API, but if it's not 
too difficult I think it would be a good option.

> v2: Add the new attribute to both MJPEG and uncompressedframe descriptos
> in Documentation/ABI, with note that it was added only in a later
> kernel version
> 
> Signed-off-by: Joel Pepper <joel.pep...@rwth-aachen.de>
> ---
>  Documentation/ABI/testing/configfs-usb-gadget-uvc | 17 +
>  drivers/usb/gadget/function/uvc_configfs.c|  3 +++
>  2 files changed, 20 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc
> b/Documentation/ABI/testing/configfs-usb-gadget-uvc index 1ba0d0f..d435cf7
> 100644
> --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
> +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
> @@ -194,6 +194,14 @@ Description: Specific MJPEG frame descriptors
>   bmCapabilities  - still image support, fixed frame-rate
>   support
> 
> +Date:Mar 2018
> +KernelVersion:   4.16
> +
> + bFrameIndex - unique id for this framedescriptor;
> + if using multiple framedescriptors for
> + same format, user needs to set distinct
> + value for each frame descriptor
> +
>  What:/config/usb-gadget/gadget/functions/uvc.name/streaming/
uncompressed
>  Date:Dec 2014
>  KernelVersion:   4.0
> @@ -241,6 +249,15 @@ Description: Specific uncompressed frame descriptors
>   bmCapabilities  - still image support, fixed frame-rate
>   support
> 
> +Date:   Mar 2018
> +KernelVersion:  4.16
> +
> +bFrameIndex - unique id for this
> framedescriptor; +if using multiple
> framedescriptors for +same format,
> user needs to set distinct +value
> for each frame descriptor +
> +
>  What:
> /config/usb-gadget/gadget/functions/uvc.name/streaming/header
>  Date:Dec 2014
>  KernelVersion:   4.0
> diff --git a/drivers/usb/gadget/function/uvc_configfs.c
> b/drivers/usb/gadget/function/uvc_configfs.c index c9b8cc4a..5966d65 100644
> --- a/drivers/usb/gadget/function/uvc_configfs.c
> +++ b/drivers/usb/gadget/function/uvc_configfs.c
> @@ -992,6 +992,8 @@ UVC_ATTR(uvcg_frame_, cname, aname);
> 
>  UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
>   noop_conversion, 8);
> +UVCG_FRAME_ATTR(b_frame_index, bFrameIndex, noop_conversion,
> + noop_conversion, 8);
>  UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
>  UVCG_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16);
>  UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32,
> 32);
> @@ -1137,6 +1139,7 @@ UVC_ATTR(uvcg_frame_, dw_frame_interval,
> dwFrameInterval);
> 
>  static struct configfs_attribute *uvcg_frame_attrs[] = {
>   _frame_attr_bm_capabilities,
> + _frame_attr_b_frame_index,
>   _frame_attr_w_width,
>  

Re: Some questions about the UVC gadget

2018-02-22 Thread Laurent Pinchart
Hello Kelly,

(CC'ing Paul Elder)

On Thursday, 22 February 2018 11:03:42 EET Felipe Balbi wrote:
> Kelly Huang writes:
> >  Dear Mr.Balbi,
> > 
> > I am a college student from China. Recently, I am doing some research on
> > the UVC gadget. After reading the source code, I found that the uvc gadget
> > framework only supports two types of video streaming format, the
> > UNCOMPRESSED and the MJPEG.
> > 
> > Now, I am trying to add H.264 support. I wonder if the Linux kernel has
> > already support it or not. It will be appreciated if you can give me some
> > advice.
> > 
> > Thank you for your time.
> 
> It's a good idea to add mailing lists and other relevant people to the
> loop.

I'm afraid the Linux UVC gadget driver doesn't support H.264. While H.264 
support could be implemented using UVC 1.1, I wouldn't recommend this as the 
UVC 1.1 H.264 specification is a hack that is not and will not be supported in 
the Linux UVC host driver. UVC 1.5 is the way to go for H.264. This shouldn't 
be too difficult to implement on the gadget side, but the host UVC driver also 
misses UVC 1.5 support.

Paul has recently started working on the UVC gadget driver to revive it along 
with the userspace helper application. Further down on his to-do list he told 
me he would like to implement UVC 1.5 support on the host side, but that won't 
be for the near future (no pressure Paul :-)).

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 21/24] USB: gadget: legacy: Remove redundant license text

2017-11-06 Thread Laurent Pinchart
Hi Greg,

Thank you for the patch.

On Monday, 6 November 2017 16:37:30 EET Greg Kroah-Hartman wrote:
> Now that the SPDX tag is in all USB files, that identifies the license
> in a specific and legally-defined manner.  So the extra GPL text wording
> can be removed as it is no longer needed at all.
> 
> This is done on a quest to remove the 700+ different ways that files in
> the kernel describe the GPL license text.  And there's unneeded stuff
> like the address (sometimes incorrect) for the FSF which is never
> needed.
> 
> No copyright headers or other non-license-description text was removed.
> 
> Cc: Felipe Balbi <ba...@kernel.org>
> Cc: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
> Cc: Johan Hovold <jo...@kernel.org>
> Cc: Ruslan Bilovol <ruslan.bilo...@gmail.com>
> Cc: Peter Chen <peter.c...@nxp.com>
> Cc: Alan Stern <st...@rowland.harvard.edu>
> Cc: David Windsor <dwind...@gmail.com>
> Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>

> ---
>  drivers/usb/gadget/legacy/acm_ms.c | 5 -
>  drivers/usb/gadget/legacy/audio.c  | 2 --
>  drivers/usb/gadget/legacy/cdc2.c   | 5 -
>  drivers/usb/gadget/legacy/ether.c  | 5 -
>  drivers/usb/gadget/legacy/g_ffs.c  | 5 -
>  drivers/usb/gadget/legacy/gmidi.c  | 3 ---
>  drivers/usb/gadget/legacy/hid.c| 5 -
>  drivers/usb/gadget/legacy/inode.c  | 5 -
>  drivers/usb/gadget/legacy/mass_storage.c   | 5 -
>  drivers/usb/gadget/legacy/multi.c  | 5 -
>  drivers/usb/gadget/legacy/ncm.c| 5 -
>  drivers/usb/gadget/legacy/nokia.c  | 4 
>  drivers/usb/gadget/legacy/printer.c| 5 -
>  drivers/usb/gadget/legacy/serial.c | 4 
>  drivers/usb/gadget/legacy/tcm_usb_gadget.c | 1 -
>  drivers/usb/gadget/legacy/webcam.c | 5 -
>  drivers/usb/gadget/legacy/zero.c   | 5 -
>  17 files changed, 74 deletions(-)

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 23/24] USB: gadget: function: Remove redundant license text

2017-11-06 Thread Laurent Pinchart
Hi Greg,

Thank you for the patch.

On Monday, 6 November 2017 16:37:32 EET Greg Kroah-Hartman wrote:
> Now that the SPDX tag is in all USB files, that identifies the license
> in a specific and legally-defined manner.  So the extra GPL text wording
> can be removed as it is no longer needed at all.
> 
> This is done on a quest to remove the 700+ different ways that files in
> the kernel describe the GPL license text.  And there's unneeded stuff
> like the address (sometimes incorrect) for the FSF which is never
> needed.
> 
> No copyright headers or other non-license-description text was removed.
> 
> Cc: Felipe Balbi <ba...@kernel.org>
> Cc: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
> Cc: Oliver Neukum <oneu...@suse.com>
> Cc: Johan Hovold <jo...@kernel.org>
> Cc: Michal Nazarewicz <min...@mina86.com>
> Cc: Vincent Pelletier <plr.vinc...@gmail.com>
> Cc: Jerry Zhang <zhangje...@google.com>
> Cc: John Keeping <j...@metanate.com>
> Cc: Krzysztof Opasiak <k.opas...@samsung.com>
> Cc: Abdulhadi Mohamed <abdulahha...@gmail.com>
> Cc: Matthew Wilcox <wi...@linux.intel.com>
> Cc: Janusz Dziedzic <januszx.dzied...@linux.intel.com>
> Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>

I have however not checked whether the SPDX tag matches the license text for 
every file (GPLv2 vs. GPLv2+), I expect that to have been verified when the 
SPDX tags got merged.

> ---
>  drivers/usb/gadget/function/f_acm.c|  4 
>  drivers/usb/gadget/function/f_ecm.c|  5 -
>  drivers/usb/gadget/function/f_eem.c|  5 -
>  drivers/usb/gadget/function/f_fs.c |  5 -
>  drivers/usb/gadget/function/f_hid.c|  5 -
>  drivers/usb/gadget/function/f_loopback.c   |  5 -
>  drivers/usb/gadget/function/f_midi.c   |  2 --
>  drivers/usb/gadget/function/f_ncm.c|  5 -
>  drivers/usb/gadget/function/f_obex.c   |  5 -
>  drivers/usb/gadget/function/f_phonet.c |  4 
>  drivers/usb/gadget/function/f_printer.c|  5 -
>  drivers/usb/gadget/function/f_rndis.c  |  5 -
>  drivers/usb/gadget/function/f_serial.c |  4 
>  drivers/usb/gadget/function/f_sourcesink.c |  5 -
>  drivers/usb/gadget/function/f_subset.c |  5 -
>  drivers/usb/gadget/function/f_tcm.c|  1 -
>  drivers/usb/gadget/function/f_uac1.c   |  5 -
>  drivers/usb/gadget/function/f_uac1_legacy.c|  2 --
>  drivers/usb/gadget/function/f_uac2.c   |  5 -
>  drivers/usb/gadget/function/f_uvc.c|  5 -
>  drivers/usb/gadget/function/f_uvc.h|  5 -
>  drivers/usb/gadget/function/rndis.c|  4 
>  drivers/usb/gadget/function/rndis.h|  4 
>  drivers/usb/gadget/function/storage_common.c   |  5 -
>  drivers/usb/gadget/function/u_audio.c  | 10 --
>  drivers/usb/gadget/function/u_audio.h  | 11 ---
>  drivers/usb/gadget/function/u_ecm.h|  4 
>  drivers/usb/gadget/function/u_eem.h|  4 
>  drivers/usb/gadget/function/u_ether.c  |  5 -
>  drivers/usb/gadget/function/u_ether.h  |  5 -
>  drivers/usb/gadget/function/u_ether_configfs.h |  4 
>  drivers/usb/gadget/function/u_fs.h |  4 
>  drivers/usb/gadget/function/u_gether.h |  4 
>  drivers/usb/gadget/function/u_hid.h|  4 
>  drivers/usb/gadget/function/u_midi.h   |  4 
>  drivers/usb/gadget/function/u_ncm.h|  4 
>  drivers/usb/gadget/function/u_phonet.h |  4 
>  drivers/usb/gadget/function/u_printer.h|  4 
>  drivers/usb/gadget/function/u_rndis.h  |  4 
>  drivers/usb/gadget/function/u_serial.c |  4 
>  drivers/usb/gadget/function/u_serial.h |  4 
>  drivers/usb/gadget/function/u_tcm.h|  4 
>  drivers/usb/gadget/function/u_uac1.h   |  4 
>  drivers/usb/gadget/function/u_uac1_legacy.c|  2 --
>  drivers/usb/gadget/function/u_uac1_legacy.h|  2 --
>  drivers/usb/gadget/function/u_uac2.h   |  4 
>  drivers/usb/gadget/function/u_uvc.h|  4 
>  drivers/usb/gadget/function/uvc.h  |  5 -
>  drivers/usb/gadget/function/uvc_configfs.c |  4 
>  drivers/usb/gadget/function/uvc_configfs.h |  4 
>  drivers/usb/gadget/function/uvc_queue.c    |  5 -
>  drivers/usb/gadget/function/uvc_v4l2.c |  5 -
>  drivers/usb/gadget/function/uvc_v4l2.h |  4 
>

Re: [PATCH v2 02/15] usb: gadget: make config_item_type structures const

2017-10-19 Thread Laurent Pinchart
Hi Christoph,

On Thursday, 19 October 2017 17:06:57 EEST Christoph Hellwig wrote:
> > Now we have 9 const instances of the config_item_type structure that are
> > identical, with only the .ct_owner field set. Should they be all merged
> > into a single structure ?
> 
> I think that's a good idea.
> 
> But I'm about to slurp up this whole series into my tree, how about making
> that an incremental patch?

I'm fine with that.

Bhumika, would you like to submit an incremental patch, or should I do it ?

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 02/15] usb: gadget: make config_item_type structures const

2017-10-18 Thread Laurent Pinchart
ng_class_type = {
> +static const struct config_item_type uvcg_streaming_class_type = {
>   .ct_item_ops= _streaming_class_item_ops,
>   .ct_owner   = THIS_MODULE,
>  };
> @@ -2095,7 +2095,7 @@ static void uvcg_streaming_class_drop_link(struct
> config_item *src, struct config_group group;
>  } uvcg_streaming_class_grp;
> 
> -static struct config_item_type uvcg_streaming_class_grp_type = {
> +static const struct config_item_type uvcg_streaming_class_grp_type = {
>   .ct_owner = THIS_MODULE,
>  };
> 
> @@ -2104,7 +2104,7 @@ static void uvcg_streaming_class_drop_link(struct
> config_item *src, struct config_group group;
>  } uvcg_streaming_grp;
> 
> -static struct config_item_type uvcg_streaming_grp_type = {
> +static const struct config_item_type uvcg_streaming_grp_type = {
>   .ct_owner = THIS_MODULE,
>  };

Now we have 9 const instances of the config_item_type structure that are 
identical, with only the .ct_owner field set. Should they be all merged into a 
single structure ?

> @@ -2190,7 +2190,7 @@ static void uvc_attr_release(struct config_item *item)
> NULL,
>  };
> 
> -static struct config_item_type uvc_func_type = {
> +static const struct config_item_type uvc_func_type = {
>   .ct_item_ops= _item_ops,
>   .ct_attrs   = uvc_attrs,
>   .ct_owner   = THIS_MODULE,


-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 1/4] dt-bindings: add bindings for USB physical connector

2017-10-18 Thread Laurent Pinchart
Hi Andrzej,

On Wednesday, 18 October 2017 18:11:25 EEST Laurent Pinchart wrote:
> On Thursday, 28 September 2017 16:07:27 EEST Andrzej Hajda wrote:
> > These bindings allows to describe most known standard USB connectors
> > and it should be possible to extend it if necessary.
> > USB connectors, beside USB can be used to route other protocols,
> > for example UART, Audio, MHL. In such case every device passing data
> > through the connector should have appropriate graph bindings.
> > 
> > Signed-off-by: Andrzej Hajda <a.ha...@samsung.com>
> > ---
> > There are few things for discussion (IMO):
> > 1. vendor specific connectors, I have added them here, but maybe better is
> > 
> >to place them in separate files.
> 
> It's useful to have one vendor-specific compatible string to be used in the
> example. We could split vendor-specific connectors to separate files later
> if needed, but for now I'm fine keeping them here.
> 
> > 2. physical connector description - I have split it to three properties:
> >type(a,b,ab,c), max-mode(ls,fs,hs,ss,ss+), size(mini,micro,powered).
> >This tripled is able to describe all USB-standard connectors, but there
> >are also impossible combinations, for example(c, *, micro). Maybe
> >better
> >would be to just enumerate all possible connectors in include file.
> 
> I don't have a strong opinion on this. The three properties are nicely
> descriptive. You might want to list the valid combinations in the bindings
> though.
> 
> > 3. Numbering of port/remote nodes, currently only 0 is assigned for
> > 
> > Interface Controller. Maybe other functions should be also assigned:
> >HS, SS, CC, SBU, ... whatever. Maybe functions should be described
> >as an additional property of remote node?
> 
> Given that one of the main reasons this binding is needed is to describe MHL
> connection to a USB connector, I think we'll need to define additional
> functions, yes. I'm not sure yet how that should look like though.
> > ---
> > 
> >  .../bindings/connector/usb-connector.txt   | 49 +
> >  1 file changed, 49 insertions(+)
> >  create mode 100644
> > 
> > Documentation/devicetree/bindings/connector/usb-connector.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt
> > b/Documentation/devicetree/bindings/connector/usb-connector.txt new file
> > mode 100644
> > index ..f3a4e85122d5
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt
> > @@ -0,0 +1,49 @@
> > +USB Connector
> > +=
> > +
> > +Required properties:
> > +- compatible: "usb-connector"
> > +  connectors with vendor specific extensions can add one of additional
> > +  compatibles:
> > +"samsung,usb-connector-11pin": 11-pin Samsung micro-USB connector
> > +- type: the USB connector type: "a", "b", "ab", "c"
> > +- max-mode: max USB speed mode supported by the connector:
> > +  "ls", "fs", "hs", "ss", "ss+"
> > +
> > +Optional properties:
> > +- label: a symbolic name for the connector
> > +- size: size of the connector, should be specified in case of
> > +  non-standard USB connectors: "mini", "micro", "powered"
> 
> "non-standard" sounds like "vendor-specific", while I assume you're talking
> about the size. The USB specification uses the term "standard" for this
> purpose, so it's hard to use another one that would convey the right meaning
> precisely. Maybe "non-standard ('large') USB connector sizes" ?
> 
> > +Required nodes:
> > +- any data bus to the connector should be modeled using the
> > +  OF graph bindings specified in bindings/graph.txt.
> > +  There should be exactly one port with at least one endpoint to
> > +  different device nodes. The first endpoint (reg = <0>) should
> > +  point to USB Interface Controller.
> > +
> > +Example
> > +---
> > +
> > +musb_con: connector {
> > +   compatible = "samsung,usb-connector-11pin", "usb-connector";
> > +   label = "usb";
> > +   type = "b";
> > +   size = "micro";
> > +   max-mode = "hs";
> > +
> > +   port {
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +
> > +   musb_con_usb_in: endpoint@0 {
> > +   reg = <0>;
> > +   remote-endpoint = <_usb_out>;
> > +   };
> > +
> > +   musb_con_mhl_in: endpoint@1 {
> > +   reg = <1>;
> > +   remote-endpoint = <_out>;
> > +   };
> > +   };
> > +};

One more comment, do I assume correctly that the Samsung 11-pin connector 
carries USB and MHL on different pins ?

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 1/4] dt-bindings: add bindings for USB physical connector

2017-10-18 Thread Laurent Pinchart
Hi Andrzej,

Thank you for the patch.

On Thursday, 28 September 2017 16:07:27 EEST Andrzej Hajda wrote:
> These bindings allows to describe most known standard USB connectors
> and it should be possible to extend it if necessary.
> USB connectors, beside USB can be used to route other protocols,
> for example UART, Audio, MHL. In such case every device passing data
> through the connector should have appropriate graph bindings.
> 
> Signed-off-by: Andrzej Hajda <a.ha...@samsung.com>
> ---
> There are few things for discussion (IMO):
> 1. vendor specific connectors, I have added them here, but maybe better is
>to place them in separate files.

It's useful to have one vendor-specific compatible string to be used in the 
example. We could split vendor-specific connectors to separate files later if 
needed, but for now I'm fine keeping them here.

> 2. physical connector description - I have split it to three properties:
>type(a,b,ab,c), max-mode(ls,fs,hs,ss,ss+), size(mini,micro,powered).
>This tripled is able to describe all USB-standard connectors, but there
>are also impossible combinations, for example(c, *, micro). Maybe better
>would be to just enumerate all possible connectors in include file.

I don't have a strong opinion on this. The three properties are nicely 
descriptive. You might want to list the valid combinations in the bindings 
though.

> 3. Numbering of port/remote nodes, currently only 0 is assigned for
> Interface Controller. Maybe other functions should be also assigned:
>HS, SS, CC, SBU, ... whatever. Maybe functions should be described
>as an additional property of remote node?

Given that one of the main reasons this binding is needed is to describe MHL 
connection to a USB connector, I think we'll need to define additional 
functions, yes. I'm not sure yet how that should look like though.

> ---
>  .../bindings/connector/usb-connector.txt   | 49 +++
>  1 file changed, 49 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/connector/usb-connector.txt
> 
> diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt
> b/Documentation/devicetree/bindings/connector/usb-connector.txt new file
> mode 100644
> index ..f3a4e85122d5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt
> @@ -0,0 +1,49 @@
> +USB Connector
> +=
> +
> +Required properties:
> +- compatible: "usb-connector"
> +  connectors with vendor specific extensions can add one of additional
> +  compatibles:
> +"samsung,usb-connector-11pin": 11-pin Samsung micro-USB connector
> +- type: the USB connector type: "a", "b", "ab", "c"
> +- max-mode: max USB speed mode supported by the connector:
> +  "ls", "fs", "hs", "ss", "ss+"
> +
> +Optional properties:
> +- label: a symbolic name for the connector
> +- size: size of the connector, should be specified in case of
> +  non-standard USB connectors: "mini", "micro", "powered"

"non-standard" sounds like "vendor-specific", while I assume you're talking 
about the size. The USB specification uses the term "standard" for this 
purpose, so it's hard to use another one that would convey the right meaning 
precisely. Maybe "non-standard ('large') USB connector sizes" ?

> +Required nodes:
> +- any data bus to the connector should be modeled using the
> +  OF graph bindings specified in bindings/graph.txt.
> +  There should be exactly one port with at least one endpoint to
> +  different device nodes. The first endpoint (reg = <0>) should
> +  point to USB Interface Controller.
> +
> +Example
> +---
> +
> +musb_con: connector {
> + compatible = "samsung,usb-connector-11pin", "usb-connector";
> + label = "usb";
> + type = "b";
> + size = "micro";
> + max-mode = "hs";
> +
> + port {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + musb_con_usb_in: endpoint@0 {
> + reg = <0>;
> + remote-endpoint = <_usb_out>;
> + };
> +
> + musb_con_mhl_in: endpoint@1 {
> + reg = <1>;
> + remote-endpoint = <_out>;
> + };
> + };
> +};

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/9] USB: gadget: remove unneeded MODULE_VERSION() usage

2017-07-19 Thread Laurent Pinchart
Hi Greg,

Thank you for the patch.

On Wednesday 19 Jul 2017 14:17:39 Greg Kroah-Hartman wrote:
> MODULE_VERSION is useless for in-kernel drivers, so just remove all
> usage of it in the USB gadget drivers.  Along with this, some
> DRIVER_VERSION macros were removed as they are also pointless.
> 
> Cc: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
> Cc: Felipe Balbi <ba...@kernel.org>
> Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
> ---
>  drivers/usb/gadget/legacy/webcam.c   | 1 -

Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>

>  drivers/usb/gadget/udc/mv_udc_core.c | 2 --
>  drivers/usb/gadget/udc/s3c2410_udc.c | 4 +---
>  3 files changed, 1 insertion(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/gadget/legacy/webcam.c
> b/drivers/usb/gadget/legacy/webcam.c index f9661cd627c8..82c13fce9232
> 100644
> --- a/drivers/usb/gadget/legacy/webcam.c
> +++ b/drivers/usb/gadget/legacy/webcam.c
> @@ -436,5 +436,4 @@ module_usb_composite_driver(webcam_driver);
>  MODULE_AUTHOR("Laurent Pinchart");
>  MODULE_DESCRIPTION("Webcam Video Gadget");
>  MODULE_LICENSE("GPL");
> -MODULE_VERSION("0.1.0");
> 
> diff --git a/drivers/usb/gadget/udc/mv_udc_core.c
> b/drivers/usb/gadget/udc/mv_udc_core.c index 8a708d0a1042..4103bf7cf52a
> 100644
> --- a/drivers/usb/gadget/udc/mv_udc_core.c
> +++ b/drivers/usb/gadget/udc/mv_udc_core.c
> @@ -39,7 +39,6 @@
>  #include "mv_udc.h"
> 
>  #define DRIVER_DESC  "Marvell PXA USB Device Controller driver"
> -#define DRIVER_VERSION   "8 Nov 2010"
> 
>  #define ep_dir(ep)   (((ep)->ep_num == 0) ? \
>   ((ep)->udc->ep0_dir) : ((ep)->direction))
> @@ -2427,5 +2426,4 @@ module_platform_driver(udc_driver);
>  MODULE_ALIAS("platform:mv-udc");
>  MODULE_DESCRIPTION(DRIVER_DESC);
>  MODULE_AUTHOR("Chao Xie <chao@marvell.com>");
> -MODULE_VERSION(DRIVER_VERSION);
>  MODULE_LICENSE("GPL");
> diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c
> b/drivers/usb/gadget/udc/s3c2410_udc.c index 4643a01262b4..394abd5d65c0
> 100644
> --- a/drivers/usb/gadget/udc/s3c2410_udc.c
> +++ b/drivers/usb/gadget/udc/s3c2410_udc.c
> @@ -51,7 +51,6 @@
>  #include "s3c2410_udc.h"
> 
>  #define DRIVER_DESC  "S3C2410 USB Device Controller Gadget"
> -#define DRIVER_VERSION   "29 Apr 2007"
>  #define DRIVER_AUTHOR"Herbert Pƶtzl <herb...@13thfloor.at>, " \
>   "Arnaud Patard <arnaud.pat...@rtp-net.org>"
> 
> @@ -1996,7 +1995,7 @@ static int __init udc_init(void)
>  {
>   int retval;
> 
> - dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, 
DRIVER_VERSION);
> + dprintk(DEBUG_NORMAL, "%s\n", gadget_name);
> 
>   s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
>   if (IS_ERR(s3c2410_udc_debugfs_root)) {
> @@ -2027,5 +2026,4 @@ module_exit(udc_exit);
> 
>  MODULE_AUTHOR(DRIVER_AUTHOR);
>  MODULE_DESCRIPTION(DRIVER_DESC);
> -MODULE_VERSION(DRIVER_VERSION);
>  MODULE_LICENSE("GPL");

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Chipidea USB controller hangs in peripheral mode under high memory bus pressure

2017-05-15 Thread Laurent Pinchart
Hi Thomas,

On Monday 08 May 2017 04:42:59 Thomas Entner / EE wrote:
> Am 08.05.2017 um 03:56 schrieb Peter Chen:
> > On Fri, May 05, 2017 at 04:10:14PM +0200, Thomas Entner / EE wrote:
> >> Am 05.05.2017 um 14:56 schrieb Thomas Entner / EE:
> >>> Hi, I am Thomas who contacted Laurent regarding this issue. We have some
> >>> further observations:
> >>> 
> >>> Am 04.05.2017 um 08:45 schrieb Peter Chen:
> >>>> On Wed, May 03, 2017 at 01:32:28PM +0300, Laurent Pinchart wrote:
> >>>>>> There was no one reported this problem before, but from the
> >>>>>> description, it seems an IC issue which is triggered at high loading
> >>>>>> memory bus, controller may not get time to visit memory at limited
> >>>>>> time.
> >>>>> 
> >>>>> That's my guess too. I was expecting the USB controller's bus master
> >>>>> interface to get stalled but eventually perform the access (or retry
> >>>>> it, I'm not sure what kind of bus it sits on), but there might be a
> >>>>> hardware bug that messes up the controller's state machine. I won't
> >>>>> rule out the possibility of a software issue yet, it might be possible
> >>>>> to detect this condition and retry the transfer.
> >>>> 
> >>>> I am not sure if it can be recovered, you can call ->fifo_flush, and
> >>>> ->ep_disable and ->ep_enable if it returns -ETIME, and re-submit this
> >>>> request.
> >>>> 
> >>>>>> At Xilinx Zynq, its tx buffer is small, and less than 512 bytes
> >>>>>> (84bc70f94d81, "usb: chipidea: add xilinx zynq platform data"), and
> >>>>>> your throughput may be > (512 * 3) bytes/SoF, you can't use non-
> >>>>>> stream mode by reducing max packet size.
> >>>>> 
> >>>>> My throughput is actually 1*1024 bytes / SOF.
> >>>>> 
> >>>> >From previous discussion, the tx fifo size is 341.33 bytes for xilinx
> >>>> 
> >>>> zynq, you can set max packet size as 341 and mult as 3, then you can
> >>>> transfer 1023 bytes / SoF for non-stream mode, assumed the non-stream
> >>>> mode can fix your problem.
> >>> 
> >>> I am not sure if this is totally correct: Xilinx UG585, page 1815,
> >>> register HWTXBUF (TXADD), the TxBuffer size of the Xilinx controller is
> >>> only 768 Bytes. However, I think you are correct that the issue is
> >>> related to this topic:
> >>> 
> >>> When we reduce the max packet size to 512, we no longer get the full
> >>> lock-ups, but UVC streaming still stops after some time (under have
> >>> memory traffic).
> >>> 
> >>> When we reduce the max packet size to 256, things appear to work stable
> >>> (but very slow).
> >>> 
> >>> When we use a max packet size of 720 we still see lock-ups (which is a
> >>> bit of surprise to me, I would have expected something close to 768 to
> >>> be the magical limit).
> >> 
> >> We have further debugged the issue now with a USB bus analyzer and made a
> >> (for us) surprising observation:
> >> 
> >> Both the lock-ups (packet size = 1024) and the stop of streaming without
> >> lock-up (packet size = 512) always happen at the end of a UVC frame (i.e.
> >> end of image). We can see the payload header (e.g. 02 83) with the EOF
> >> bit set, but that packet has a CRC error (end the end of the packet is
> >> not FF D9, as it should be for our MJPEG payload), I assume because the
> >> Tx-buffer did underrun.
> >> 
> >> My present understanding was that the DMA of the Chipidea IP was not able
> >> to fast enough refill the Tx buffer, but then I would expect this to
> >> happen also e.g. in the middle of the image and not only at the last
> >> transfer?
> >
> > From the below commit:
> > 84bc70f94d81 ("usb: chipidea: add xilinx zynq platform data"), the tx
> > fifo is less than 512 Bytes, you may calculate it through [1]
> > 
> > 
> > [1] https://www.spinics.net/lists/linux-usb/msg129116.html
> 
> Just very brief, should go to bed now...:
> We have a interim workaround:
> - We use 3072 packet size (3x1024), but always queue only one buffer.
> This prevents the lock-up issue. (We want to revisit this later for a
> better workaround.)
> - However, we still see CRC errors. This could be maybe related to this
> very small buffer? As the CRC errors are seldom, we can accept them. But
> to understand the root cause of this CRC errors would be very
> interesting (I think this CRC error also triggers the bad ATDTW behavior.
> - But when there is a CRC error, streaming still stopped. The reason
> was, that in case of an -EILSEQ (caused by CRC error) the request
> complete callback was not called. I have patched this in the driver.
> - I can provide you the patch later if you are interested, but I am not
> sure if it is good enough for all situations were the Chipidea IP is used...

I would appreciate if you could provide the patch, as I'm interested in 
integrating that fix in the upstream uvcvideo driver.

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Chipidea USB controller hangs in peripheral mode under high memory bus pressure

2017-05-03 Thread Laurent Pinchart
Hi Peter,

On Wednesday 03 May 2017 11:10:55 Peter Chen wrote:
> On Tue, May 02, 2017 at 03:07:03PM +0300, Laurent Pinchart wrote:
> > Hello,
> > 
> > I ran into an issue with a Xilinx Zynq XC7Z010 system. The system acts as
> > a USB peripheral, using the UVC gadget driver.
> > 
> > When transferring high bandwidth data over USB in isochronous mode,
> > complete system freezes are occasionally noticed. The problem was traced
> > to the following code from _hardware_enqueue() in
> > drivers/usb/chipidea/udc.c.
> >
> > wmb();
> > if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
> > goto done;
> > do {
> > hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
> > tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
> > } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
> > hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
> > if (tmp_stat)
> > goto done;
> > 
> > The do ... while loop loops forever, and as the function is called under a
> > spin_lock_irqsave(), the system doesn't appreciate. Adding a maximum
> > number of iterations to exit the loop is easy (I'll try to submit a patch
> > after finding the root cause of the problem). That fixes the system hang,
> > but USB transfers are still broken.
> > 
> > I've checked the code and unfortunately it seems to match the procedure
> > documented in the datasheet :-/
> > 
> > The MTBF is several hours, but running 'memtester -M100'
> > (http://pyropus.ca/software/memtester/) in parallel to UVC video transfer
> > over USB brings the MTBF to a few minutes. The problem thus seems to be
> > related to memory bus pressure.
> > 
> > Has anyone run into this problem before ? Is this a known issue ? I don't
> > mind getting my hands dirty debugging, but as I'm not familiar with the
> > chipidea USB controller pointers to what I should check in priority would
> > be appreciated.
> 
> There was no one reported this problem before, but from the description,
> it seems an IC issue which is triggered at high loading memory bus,
> controller may not get time to visit memory at limited time. At
> Xilinx Zynq, its tx buffer is small, and less than 512 bytes (84bc70f94d81,
> "usb: chipidea: add xilinx zynq platform data"), and your throughput
> may be > (512 * 3) bytes/SoF, you can't use non-stream mode by reducing
> max packet size. I think you may observe many under-run at bus analyzer
> during the test.
> 
> As a workaround, you may try to do below things:
> 
> 1. Link more TDs before the UVC run
> 2. Comment out the code, you are stuck in, it is only useful for protect
> last td status which is handling or will be handled soon by hardware.
>   /*
>   do {
>   hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
>   tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
>   } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
>   hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
>   if (tmp_stat)
>   goto done;
>   */
> 3. If it can let your test run more time, try change code like below:
> 
> if (remaining_td_num > 2)
>   don't do hardware check;
> else
>   do hardware check.
> 
> 
> Besides, I can try your test if you could show me the detail test steps.

By the way, do you have access to a Xilinx Zynq-based board for testing ? If 
you do, what board is that ? And if you don't, what board would you use ?

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Chipidea USB controller hangs in peripheral mode under high memory bus pressure

2017-05-03 Thread Laurent Pinchart
Hi Peter,

Thank you for your quick reply.

On Wednesday 03 May 2017 11:10:55 Peter Chen wrote:
> On Tue, May 02, 2017 at 03:07:03PM +0300, Laurent Pinchart wrote:
> > Hello,
> > 
> > I ran into an issue with a Xilinx Zynq XC7Z010 system. The system acts as
> > a USB peripheral, using the UVC gadget driver.
> > 
> > When transferring high bandwidth data over USB in isochronous mode,
> > complete system freezes are occasionally noticed. The problem was traced
> > to the following code from _hardware_enqueue() in
> > drivers/usb/chipidea/udc.c.
> >
> > wmb();
> > if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
> > goto done;
> > do {
> > hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
> > tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
> > } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
> > hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
> > if (tmp_stat)
> > goto done;
> > 
> > The do ... while loop loops forever, and as the function is called under a
> > spin_lock_irqsave(), the system doesn't appreciate. Adding a maximum
> > number of iterations to exit the loop is easy (I'll try to submit a patch
> > after finding the root cause of the problem). That fixes the system hang,
> > but USB transfers are still broken.
> > 
> > I've checked the code and unfortunately it seems to match the procedure
> > documented in the datasheet :-/
> > 
> > The MTBF is several hours, but running 'memtester -M100'
> > (http://pyropus.ca/software/memtester/) in parallel to UVC video transfer
> > over USB brings the MTBF to a few minutes. The problem thus seems to be
> > related to memory bus pressure.
> > 
> > Has anyone run into this problem before ? Is this a known issue ? I don't
> > mind getting my hands dirty debugging, but as I'm not familiar with the
> > chipidea USB controller pointers to what I should check in priority would
> > be appreciated.
> 
> There was no one reported this problem before, but from the description,
> it seems an IC issue which is triggered at high loading memory bus,
> controller may not get time to visit memory at limited time.

That's my guess too. I was expecting the USB controller's bus master interface 
to get stalled but eventually perform the access (or retry it, I'm not sure 
what kind of bus it sits on), but there might be a hardware bug that messes up 
the controller's state machine. I won't rule out the possibility of a software 
issue yet, it might be possible to detect this condition and retry the 
transfer.

> At Xilinx Zynq, its tx buffer is small, and less than 512 bytes
> (84bc70f94d81, "usb: chipidea: add xilinx zynq platform data"), and your
> throughput may be > (512 * 3) bytes/SoF, you can't use non-stream mode by
> reducing max packet size.

My throughput is actually 1*1024 bytes / SOF.

> I think you may observe many under-run at bus analyzer during the test.

I'll try to get this checked (as I don't have a USB analyzer here).

> As a workaround, you may try to do below things:
> 
> 1. Link more TDs before the UVC run

Do you mean I should have more requests queued to avoid hitting the 
software/hardware race that the loop handles ?

> 2. Comment out the code, you are stuck in, it is only useful for protect
> last td status which is handling or will be handled soon by hardware.
> 
>   /*
>   do {
>   hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
>   tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
>   } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
>   hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
>   if (tmp_stat)
>   goto done;
>   */

I'm not familiar with this driver, but if I understand things correctly, the 
code (and the "TD tripwire" hardware feature) is here to handle a race 
condition where the hardware could look at the last TD's next pointer at the 
same time it gets updated by the software. If I comment the code out, won't 
the endpoint will be primed unconditionally, even if it's currently executing 
transfers ? Won't that be a problem ?

> 3. If it can let your test run more time, try change code like below:
> 
> if (remaining_td_num > 2)
>   don't do hardware check;
> else
>   do hardware check.

I'll test that, but I assume I'm hitting the problem when the number of 
remaining TDs is exactly one.

> Besides, I can try your test if you could show me the detail test steps.

I need to create an easy test case, at the moment it's a complex application 
and not every part of it can be published. I'll try to provide an open-source 
test case implementation.

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Chipidea USB controller hangs in peripheral mode under high memory bus pressure

2017-05-02 Thread Laurent Pinchart
On Tuesday 02 May 2017 15:07:03 Laurent Pinchart wrote:
> Hello,
> 
> I ran into an issue with a Xilinx Zynq XC7Z010 system. The system acts as a
> USB peripheral, using the UVC gadget driver.
> 
> When transferring high bandwidth data over USB in isochronous mode, complete
> system freezes are occasionally noticed. The problem was traced to the
> following code from _hardware_enqueue() in drivers/usb/chipidea/udc.c.
> 
>   wmb();
>   if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
>   goto done;
>   do {
>   hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
>   tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
>   } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
>   hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
>   if (tmp_stat)
>   goto done;
> 
> 
> The do ... while loop loops forever, and as the function is called under a
> spin_lock_irqsave(), the system doesn't appreciate. Adding a maximum number
> of iterations to exit the loop is easy (I'll try to submit a patch after
> finding the root cause of the problem). That fixes the system hang, but USB
> transfers are still broken.
> 
> I've checked the code and unfortunately it seems to match the procedure
> documented in the datasheet :-/
> 
> The MTBF is several hours, but running 'memtester -M100'

Quick update, this should have read 'memtester 100M', sorry.

> (http://pyropus.ca/software/memtester/) in parallel to UVC video transfer
> over USB brings the MTBF to a few minutes. The problem thus seems to be
> related to memory bus pressure.
> 
> Has anyone run into this problem before ? Is this a known issue ? I don't
> mind getting my hands dirty debugging, but as I'm not familiar with the
> chipidea USB controller pointers to what I should check in priority would
> be appreciated.

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Chipidea USB controller hangs in peripheral mode under high memory bus pressure

2017-05-02 Thread Laurent Pinchart
Hello,

I ran into an issue with a Xilinx Zynq XC7Z010 system. The system acts as a 
USB peripheral, using the UVC gadget driver.

When transferring high bandwidth data over USB in isochronous mode, complete 
system freezes are occasionally noticed. The problem was traced to the 
following code from _hardware_enqueue() in drivers/usb/chipidea/udc.c.

wmb();
if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
goto done;
do {
hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
} while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
if (tmp_stat)
goto done;


The do ... while loop loops forever, and as the function is called under a 
spin_lock_irqsave(), the system doesn't appreciate. Adding a maximum number of 
iterations to exit the loop is easy (I'll try to submit a patch after finding 
the root cause of the problem). That fixes the system hang, but USB transfers 
are still broken.

I've checked the code and unfortunately it seems to match the procedure 
documented in the datasheet :-/

The MTBF is several hours, but running 'memtester -M100' 
(http://pyropus.ca/software/memtester/) in parallel to UVC video transfer over 
USB brings the MTBF to a few minutes. The problem thus seems to be related to 
memory bus pressure.

Has anyone run into this problem before ? Is this a known issue ? I don't mind 
getting my hands dirty debugging, but as I'm not familiar with the chipidea 
USB controller pointers to what I should check in priority would be 
appreciated.

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: uvc: Missing files for configfs interface

2017-03-31 Thread Laurent Pinchart
Hi Felipe and Petr,

On Tuesday 28 Mar 2017 16:48:46 Felipe Balbi wrote:
> Petr Cvek <petr.c...@tul.cz> writes:
> > Dne 7.3.2017 v 06:58 Laurent Pinchart napsal(a):
> >> On Tuesday 07 Mar 2017 00:57:20 Petr Cvek wrote:
> >>> Commit 76e0da34c7ce ("usb-gadget/uvc: use per-attribute show and store
> >>> methods") caused a stringification of an undefined macro argument
> >>> "aname", so three UVC parameters (streaming_interval,
> >>> streaming_maxpacket and streaming_maxburst) were named "aname".
> >>> 
> >>> Add the definition of "aname" to the main macro and name the filenames
> >>> as originaly intended.
> >> 
> >> Why don't you just
> >> 
> >> - UVC_ATTR(f_uvc_opts_, cname, aname)
> >> + UVC_ATTR(f_uvc_opts_, cname, cname)
> >> 
> >> in the definition of the UVCG_OPTS_ATTR() macro ?
> > 
> > Hi,
> > 
> > In a fact I did it for my first testing version. But then I realized
> > two things. First one is that someone may want to rename these three
> > files (now or in the future). The second one is that this bug was
> > caused by original author, who probably assumed the UVCG_OPTS_ATTR
> > macro had "aname" argument as others UVCG_* macros and didn't check. I
> > assumed that too and only after I saw three "aname" files with the
> > same path I realized where is the problem.
> > 
> > So it's more like a human error prone type of a code. But if you think
> > "cname" is enough I can send PATCH v2.

I think it would be, otherwise we end up passing the same argument twice, 
which seems a bit useless to me. If we ever need to rename those files we can 
always change the code later.

It's no big deal, but I have a preference for my proposal.

> Laurent, any comments?

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   3   4   5   6   >