From: Robert Baldyga <hidden> Date: 2015-07-15 06:33:02
Hello,
This patch series reworks endpoint matching and claiming mechanism in
epautoconf. From v2 there are couple of new patches adding 'ep_match'
to usb_gadget_ops and removing chip-specific quirk handling from generic
code of autoconfig.
I'm not sure if this patch set isn't too long, as it has 46 patches,
but I decided to send it as single series to avoid problems with patch
applying order.
The aim of whole patchset is to rework epautoconf code to get rid of
things like name-based endpoint matching and UDC name-based quirks in
generic code. These needed to do some modifications in framework like
adding 'endpoint capabilities flags' feature or adding 'match_ep'.
Following paragraphs contain brief description of what modifications are
done by particular parts of this patch set:
Patch (1) introduces new safer endpoint claiming method, basing on new
'claimed' flag. It was discussed here [1]. I proposed this solution over
year ago and it was accepted, but I apparently forgot to send the final
version of my patch.
Patches (2-3) add the 'capabilities flags' structure and helper macros.
This solution is inspired by the 'feature flags' originally proposed
by Felipe Balbi in 2013 [2], but unfortunately implementation of this
feature has never been completed.
Patches (4-36) add' capabilites flags' support to all UDC drivers present
in the kernel tree. It's needed to be done before replacing old endpoint
matching mechanism, otherwise UDC drivers which doesn't set 'capabilities
flags' won't work with new matching function.
Patch (37) finally replaces old endpoint matching method with the new
one basing on capabilities flags.
These changes aims to get rid of code, which guesses endpoint capabilities
basing on it's name, and introduce new better replacement. In result
we have better way to describe types and directions supported by each
endpoint.
For example the old name-based method didn't allow to have endpoint
supporing two types of transfers - there were only ability to support
one or all of endpoint types. The 'capabilities flags' feature supply
precise, flexible and extensible mechanism of description of endpoint
hardware limitations, which is desired for proper endpoint matching.
Patch (38) removes chip-specific quirk from ep_matches() function.
Patches (39-40) remove code modifying endpoint and descriptor structures
from ep_matches() function and cleans it up to make it simpler and more
readable.
Patch (41) add 'match_ep' callback to usb_gadget_ops and make use of
it in epautoconf. This callback allows UDC drivers to supply non-standard
endpoint matching algorithms.
Patches (42-43) move ep_matches() and find_ep() functions outside
epautoconf and rename them to usb_gadget_ep_match_desc() and
gadget_find_ep_by_name(). It's because they may be useful in 'match_ep'
callbacks in UDC drivers to avoid writing repetitive code.
Patches (44-46) move chip-specific enpoint matching algorithms from
generic code of usb_ep_autoconfig_ss() function to UDC controller drivers
using 'match_ep' callback.
In the result we have epautoconf source free of chip-specific code, plus
two new mechanisms allowing to handle non-standard hardware limitations.
[1] https://lkml.org/lkml/2014/6/16/94
[2] http://www.spinics.net/lists/linux-usb/msg99662.html
Best regards,
Robert Baldyga
Changelog:
v3:
- addressed comments from Sergei Shtylyov
v2: https://lkml.org/lkml/2015/7/14/172
- remove PXA quirk from ep_matches() function without behaviour change
using ep capabilities flags
- separate ep and desc configuration code from ep_match() function
- add 'ep_match' to usb_gadget_ops and move chip-specific endpoint
matching algorithms from generic code to UDC controller drivers
v1: https://lkml.org/lkml/2015/7/8/436
Robert Baldyga (46):
usb: gadget: encapsulate endpoint claiming mechanism
usb: gadget: add endpoint capabilities flags
usb: gadget: add endpoint capabilities helper macros
staging: emxx_udc: add ep capabilities support
usb: chipidea: udc: add ep capabilities support
usb: dwc2: gadget: add ep capabilities support
usb: dwc3: gadget: add ep capabilities support
usb: gadget: amd5536udc: add ep capabilities support
usb: gadget: at91_udc: add ep capabilities support
usb: gadget: bcm63xx_udc: add ep capabilities support
usb: gadget: bdc: add ep capabilities support
usb: gadget: dummy-hcd: add ep capabilities support
usb: gadget: fotg210-udc: add ep capabilities support
usb: gadget: fsl_qe_udc: add ep capabilities support
usb: gadget: fsl_udc_core: add ep capabilities support
usb: gadget: fusb300_udc: add ep capabilities support
usb: gadget: goku_udc: add ep capabilities support
usb: gadget: gr_udc: add ep capabilities support
usb: gadget: lpc32xx_udc: add ep capabilities support
usb: gadget: m66592-udc: add ep capabilities support
usb: gadget: mv_u3d_core: add ep capabilities support
usb: gadget: mv_udc_core: add ep capabilities support
usb: gadget: net2272: add ep capabilities support
usb: gadget: net2280: add ep capabilities support
usb: gadget: omap_udc: add ep capabilities support
usb: gadget: pch_ud: add ep capabilities support
usb: gadget: pxa25x_udc: add ep capabilities support
usb: gadget: pxa27x_udc: add ep capabilities support
usb: gadget: r8a66597-udc: add ep capabilities support
usb: gadget: s3c-hsudc: add ep capabilities support
usb: gadget: s3c2410_udc: add ep capabilities support
usb: gadget: udc-xilinx: add ep capabilities support
usb: isp1760: udc: add ep capabilities support
usb: musb: gadget: add ep capabilities support
usb: renesas: gadget: add ep capabilities support
usb: gadget: atmel_usba_udc: add ep capabilities support
usb: gadget: epautoconf: add endpoint capabilities flags verification
usb: gadget: epautoconf: remove pxa quirk from ep_matches()
usb: gadget: epautoconf: remove ep and desc configuration from
ep_matches()
usb: gadget: epautoconf: rework ep_matches() function
usb: gadget: add 'ep_match' callback to usb_gadget_ops
usb: gadget: move ep_matches() from epautoconf to udc-core
usb: gadget: move find_ep() from epautoconf to gadget.h
usb: gadget: net2280: add net2280_match_ep() function
usb: gadget: goku_udc: add goku_match_ep() function
usb: musb: gadget: add musb_match_ep() function
drivers/staging/emxx_udc/emxx_udc.c | 60 ++++---
drivers/usb/chipidea/udc.c | 14 ++
drivers/usb/dwc2/gadget.c | 13 ++
drivers/usb/dwc3/gadget.c | 13 ++
drivers/usb/gadget/epautoconf.c | 280 +++++---------------------------
drivers/usb/gadget/udc/amd5536udc.c | 57 +++++--
drivers/usb/gadget/udc/at91_udc.c | 33 +++-
drivers/usb/gadget/udc/atmel_usba_udc.c | 11 ++
drivers/usb/gadget/udc/bcm63xx_udc.c | 25 ++-
drivers/usb/gadget/udc/bdc/bdc_ep.c | 9 +
drivers/usb/gadget/udc/dummy_hcd.c | 65 ++++++--
drivers/usb/gadget/udc/fotg210-udc.c | 11 ++
drivers/usb/gadget/udc/fsl_qe_udc.c | 11 ++
drivers/usb/gadget/udc/fsl_udc_core.c | 13 ++
drivers/usb/gadget/udc/fusb300_udc.c | 11 ++
drivers/usb/gadget/udc/goku_udc.c | 33 ++++
drivers/usb/gadget/udc/gr_udc.c | 11 ++
drivers/usb/gadget/udc/lpc32xx_udc.c | 32 ++++
drivers/usb/gadget/udc/m66592-udc.c | 11 ++
drivers/usb/gadget/udc/mv_u3d_core.c | 9 +
drivers/usb/gadget/udc/mv_udc_core.c | 9 +
drivers/usb/gadget/udc/net2272.c | 11 ++
drivers/usb/gadget/udc/net2280.c | 81 +++++++--
drivers/usb/gadget/udc/omap_udc.c | 22 +++
drivers/usb/gadget/udc/pch_udc.c | 14 +-
drivers/usb/gadget/udc/pxa25x_udc.c | 29 ++++
drivers/usb/gadget/udc/pxa27x_udc.h | 33 ++--
drivers/usb/gadget/udc/r8a66597-udc.c | 10 ++
drivers/usb/gadget/udc/s3c-hsudc.c | 15 ++
drivers/usb/gadget/udc/s3c2410_udc.c | 10 ++
drivers/usb/gadget/udc/udc-core.c | 69 ++++++++
drivers/usb/gadget/udc/udc-xilinx.c | 9 +
drivers/usb/isp1760/isp1760-udc.c | 11 ++
drivers/usb/musb/musb_gadget.c | 46 ++++++
drivers/usb/renesas_usbhs/mod_gadget.c | 6 +
include/linux/usb/gadget.h | 71 ++++++++
36 files changed, 833 insertions(+), 335 deletions(-)
--
1.9.1
From: Robert Baldyga <hidden> Date: 2015-07-15 06:33:14
So far it was necessary for usb functions to set ep->driver_data in
endpoint obtained from autoconfig to non-null value, to indicate that
endpoint is claimed by function (in autoconfig it was checked if endpoint
has set this field to non-null value, and if it has, it was assumed that
it is claimed). It could cause bugs becouse if some function doesn't
set this field autoconfig could return the same endpoint more than one
time.
To help to avoid such bugs this patch adds claimed flag to struct usb_ep,
and encapsulates endpoint claiming mechanism inside usb_ep_autoconfig_ss()
and usb_ep_autoconfig_reset(), so now usb functions don't need to perform
any additional actions to mark endpoint obtained from autoconfig as claimed.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 11 ++++++-----
include/linux/usb/gadget.h | 1 +
2 files changed, 7 insertions(+), 5 deletions(-)
@@ -53,7 +53,7 @@ ep_matches (intnum_req_streams=0;/* endpoint already claimed? */-if(NULL!=ep->driver_data)+if(ep->claimed)return0;/* only support ep0 for portable CONTROL traffic */
From: Robert Baldyga <hidden> Date: 2015-07-15 06:33:37
Introduce struct usb_ep_caps which contains information about capabilities
of usb endpoints - supported transfer types and directions. This structure
should be filled by UDC driver for each of its endpoints, and will be
used in epautoconf in new ep matching mechanism which will replace ugly
guessing of endpoint capabilities basing on its name.
Signed-off-by: Robert Baldyga <redacted>
---
include/linux/usb/gadget.h | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
From: Robert Baldyga <hidden> Date: 2015-07-15 06:33:43
Add macros useful while initializing array of endpoint capabilities
structures. These macros makes structure initialization more compact
to decrease number of code lines and increase readability of code.
Signed-off-by: Robert Baldyga <redacted>
---
include/linux/usb/gadget.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
@@ -1952,12 +1952,18 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)ep->bdc=bdc;ep->dir=dir;+if(dir)+ep->usb_ep.caps.dir_in=true;+else+ep->usb_ep.caps.dir_out=true;+/* ep->ep_num is the index inside bdc_ep */if(epnum==1){ep->ep_num=1;bdc->bdc_ep_array[ep->ep_num]=ep;snprintf(ep->name,sizeof(ep->name),"ep%d",epnum-1);usb_ep_set_maxpacket_limit(&ep->usb_ep,EP0_MAX_PKT_SIZE);+ep->usb_ep.caps.type_control=true;ep->comp_desc=NULL;bdc->gadget.ep0=&ep->usb_ep;}else{
@@ -127,23 +127,57 @@ static inline struct dummy_request *usb_request_to_dummy_requeststaticconstcharep0name[]="ep0";-staticconstchar*constep_name[]={-ep0name,/* everyone has ep0 */+staticconststruct{+constchar*name;+conststructusb_ep_capscaps;+}ep_info[]={+#define EP_INFO(_name, _type, _dir) \+{\+.name=_name,\+.caps=USB_EP_CAPS(USB_EP_CAPS_TYPE_##_type,\+USB_EP_CAPS_DIR_##_dir),\+}+/* everyone has ep0 */+EP_INFO(ep0name,CONTROL,ALL),/* act like a pxa250: fifteen fixed function endpoints */-"ep1in-bulk","ep2out-bulk","ep3in-iso","ep4out-iso","ep5in-int",-"ep6in-bulk","ep7out-bulk","ep8in-iso","ep9out-iso","ep10in-int",-"ep11in-bulk","ep12out-bulk","ep13in-iso","ep14out-iso",-"ep15in-int",-+EP_INFO("ep1in-bulk",BULK,IN),+EP_INFO("ep2out-bulk",BULK,OUT),+EP_INFO("ep3in-iso",ISO,IN),+EP_INFO("ep4out-iso",ISO,OUT),+EP_INFO("ep5in-int",INT,IN),+EP_INFO("ep6in-bulk",BULK,IN),+EP_INFO("ep7out-bulk",BULK,OUT),+EP_INFO("ep8in-iso",ISO,IN),+EP_INFO("ep9out-iso",ISO,OUT),+EP_INFO("ep10in-int",INT,IN),+EP_INFO("ep11in-bulk",BULK,IN),+EP_INFO("ep12out-bulk",BULK,OUT),+EP_INFO("ep13in-iso",ISO,IN),+EP_INFO("ep14out-iso",ISO,OUT),+EP_INFO("ep15in-int",INT,IN),/* or like sa1100: two fixed function endpoints */-"ep1out-bulk","ep2in-bulk",-+EP_INFO("ep1out-bulk",BULK,OUT),+EP_INFO("ep2in-bulk",BULK,IN),/* and now some generic EPs so we have enough in multi config */-"ep3out","ep4in","ep5out","ep6out","ep7in","ep8out","ep9in",-"ep10out","ep11out","ep12in","ep13out","ep14in","ep15out",+EP_INFO("ep3out",ALL,OUT),+EP_INFO("ep4in",ALL,IN),+EP_INFO("ep5out",ALL,OUT),+EP_INFO("ep6out",ALL,OUT),+EP_INFO("ep7in",ALL,IN),+EP_INFO("ep8out",ALL,OUT),+EP_INFO("ep9in",ALL,IN),+EP_INFO("ep10out",ALL,OUT),+EP_INFO("ep11out",ALL,OUT),+EP_INFO("ep12in",ALL,IN),+EP_INFO("ep13out",ALL,OUT),+EP_INFO("ep14in",ALL,IN),+EP_INFO("ep15out",ALL,OUT),++#undef EP_INFO};-#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name)++#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_info)/*-------------------------------------------------------------------------*/
@@ -2313,6 +2313,19 @@ static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,ep->ep.ops=&fsl_ep_ops;ep->stopped=0;+if(index==0){+ep->ep.caps.type_control=true;+}else{+ep->ep.caps.type_iso=true;+ep->ep.caps.type_bulk=true;+ep->ep.caps.type_int=true;+}++if(index&1)+ep->ep.caps.dir_in=true;+else+ep->ep.caps.dir_out=true;+/* for ep0: maxP defined in desc*forothereps,maxPissetbyepautoconfig()calledbygadgetlayer*/
@@ -2895,11 +2895,21 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)ep->in=~i&1;ep->ep.name=ep_string[i];ep->ep.ops=&pch_udc_ep_ops;-if(ep->in)+if(ep->in){ep->offset_addr=ep->num*UDC_EP_REG_SHIFT;-else+ep->ep.caps.dir_in=true;+}else{ep->offset_addr=(UDC_EPINT_OUT_SHIFT+ep->num)*UDC_EP_REG_SHIFT;+ep->ep.caps.dir_out=true;+}+if(i==UDC_EP0IN_IDX||i==UDC_EP0OUT_IDX){+ep->ep.caps.type_control=true;+}else{+ep->ep.caps.type_iso=true;+ep->ep.caps.type_bulk=true;+ep->ep.caps.type_int=true;+}/* need to set ep->ep.maxpacket and set Default Configuration?*/usb_ep_set_maxpacket_limit(&ep->ep,UDC_BULK_MAX_PKT_SIZE);list_add_tail(&ep->ep.ep_list,&dev->gadget.ep_list);
From: Robert Baldyga <hidden> Date: 2015-07-15 06:37:47
Introduce endpoint matching mechanism basing on endpoint capabilities
flags. We check if endpoint supports transfer type and direction requested
in ep descriptor. Since we have this new endpoint matching mechanism
there is no need to have old code guessing endpoint capabilities basing
on its name, so we are getting rid of it. Remove also the obsolete comment.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 96 +++++++++++++----------------------------
1 file changed, 30 insertions(+), 66 deletions(-)
@@ -56,58 +39,39 @@ ep_matches (if(ep->claimed)return0;-/* only support ep0 for portable CONTROL traffic */type=usb_endpoint_type(desc);-if(USB_ENDPOINT_XFER_CONTROL==type)-return0;--/* some other naming convention */-if('e'!=ep->name[0])+switch(type){+caseUSB_ENDPOINT_XFER_CONTROL:+/* only support ep0 for portable CONTROL traffic */return0;+caseUSB_ENDPOINT_XFER_ISOC:+if(!ep->caps.type_iso)+return0;+break;+caseUSB_ENDPOINT_XFER_BULK:+if(!ep->caps.type_bulk)+return0;+break;+caseUSB_ENDPOINT_XFER_INT:+/* bulk endpoints handle interrupt transfers,+*exceptthetoggle-quirkyiso-synchkind+*/+if(!ep->caps.type_int&&!ep->caps.type_bulk)+return0;+/* for now, avoid PXA "interrupt-in";+*it'sdocumentedasneverusingDATA1.+*/+if(gadget_is_pxa(gadget)&&ep->caps.type_int)+return0;+break;+}-/* type-restriction: "-iso", "-bulk", or "-int".-*direction-restriction:"in","out".-*/-if('-'!=ep->name[2]){-tmp=strrchr(ep->name,'-');-if(tmp){-switch(type){-caseUSB_ENDPOINT_XFER_INT:-/* bulk endpoints handle interrupt transfers,-*exceptthetoggle-quirkyiso-synchkind-*/-if('s'==tmp[2])// == "-iso"-return0;-/* for now, avoid PXA "interrupt-in";-*it'sdocumentedasneverusingDATA1.-*/-if(gadget_is_pxa(gadget)-&&'i'==tmp[1])-return0;-break;-caseUSB_ENDPOINT_XFER_BULK:-if('b'!=tmp[1])// != "-bulk"-return0;-break;-caseUSB_ENDPOINT_XFER_ISOC:-if('s'!=tmp[2])// != "-iso"-return0;-}-}else{-tmp=ep->name+strlen(ep->name);-}--/* direction-restriction: "..in-..", "out-.." */-tmp--;-if(!isdigit(*tmp)){-if(desc->bEndpointAddress&USB_DIR_IN){-if('n'!=*tmp)-return0;-}else{-if('t'!=*tmp)-return0;-}-}+if(usb_endpoint_dir_in(desc)){+if(!ep->caps.dir_in)+return0;+}else{+if(!ep->caps.dir_out)+return0;}/*
From: Robert Baldyga <hidden> Date: 2015-07-15 06:37:58
The same effect can be achieved by using capabilities flags, so now we can
get rid of handling of hardware specific limitations in generic code.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 5 -----
drivers/usb/gadget/udc/pxa25x_udc.c | 9 +++------
2 files changed, 3 insertions(+), 11 deletions(-)
From: Robert Baldyga <hidden> Date: 2015-07-15 06:38:07
Rework ep_matches() function to make it shorter and more readable.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 87 +++++++++++++++++------------------------
1 file changed, 35 insertions(+), 52 deletions(-)
@@ -30,16 +30,29 @@ ep_matches (structusb_ss_ep_comp_descriptor*ep_comp){-u8type;-u16max;--intnum_req_streams=0;+u8type;+u16max;+intnum_req_streams=0;/* endpoint already claimed? */if(ep->claimed)return0;type=usb_endpoint_type(desc);+max=0x7ff&usb_endpoint_maxp(desc);++if(usb_endpoint_dir_in(desc)&&!ep->caps.dir_in)+return0;+elseif(!ep->caps.dir_out)+return0;++if(max>ep->maxpacket_limit)+return0;++/* "high bandwidth" works only at high speed */+if(!gadget_is_dualspeed(gadget)&&usb_endpoint_maxp(desc)&(3<<11))+return0;+switch(type){caseUSB_ENDPOINT_XFER_CONTROL:/* only support ep0 for portable CONTROL traffic */
@@ -47,66 +60,36 @@ ep_matches (caseUSB_ENDPOINT_XFER_ISOC:if(!ep->caps.type_iso)return0;+/* ISO: limit 1023 bytes full speed,+*1024high/superspeed+*/+if(!gadget_is_dualspeed(gadget)&&max>1023)+return0;break;caseUSB_ENDPOINT_XFER_BULK:if(!ep->caps.type_bulk)return0;+if(ep_comp&&gadget_is_superspeed(gadget)){+/* Get the number of required streams from the+*EPcompaniondescriptorandseeiftheEP+*matchesit+*/+num_req_streams=ep_comp->bmAttributes&0x1f;+if(num_req_streams>ep->max_streams)+return0;+}break;caseUSB_ENDPOINT_XFER_INT:-/* bulk endpoints handle interrupt transfers,+/* Bulk endpoints handle interrupt transfers,*exceptthetoggle-quirkyiso-synchkind*/if(!ep->caps.type_int&&!ep->caps.type_bulk)return0;-break;-}--if(usb_endpoint_dir_in(desc)){-if(!ep->caps.dir_in)-return0;-}else{-if(!ep->caps.dir_out)-return0;-}--/*-*GetthenumberofrequiredstreamsfromtheEPcompanion-*descriptorandseeiftheEPmatchesit-*/-if(usb_endpoint_xfer_bulk(desc)){-if(ep_comp&&gadget->max_speed>=USB_SPEED_SUPER){-num_req_streams=ep_comp->bmAttributes&0x1f;-if(num_req_streams>ep->max_streams)-return0;-}--}--/* endpoint maxpacket size is an input parameter, except for bulk-*whereit'sanoutputparameterrepresentingthefullspeedlimit.-*theusbspecfixeshighspeedbulkmaxpacketat512bytes.-*/-max=0x7ff&usb_endpoint_maxp(desc);-switch(type){-caseUSB_ENDPOINT_XFER_INT:-/* INT: limit 64 bytes full speed, 1024 high/super speed */+/* INT: limit 64 bytes full speed,+*1024high/superspeed+*/if(!gadget_is_dualspeed(gadget)&&max>64)return0;-/* FALLTHROUGH */--caseUSB_ENDPOINT_XFER_ISOC:-/* ISO: limit 1023 bytes full speed, 1024 high/super speed */-if(ep->maxpacket_limit<max)-return0;-if(!gadget_is_dualspeed(gadget)&&max>1023)-return0;--/* BOTH: "high bandwidth" works only at high speed */-if((desc->wMaxPacketSize&cpu_to_le16(3<<11))){-if(!gadget_is_dualspeed(gadget))-return0;-/* configure your hardware with enough buffering!! */-}break;}
From: Robert Baldyga <hidden> Date: 2015-07-15 06:38:16
Add callback that is called by epautoconf to allow UDC driver match the
best endpoint for specific descriptor. It's intended to supply mechanism
which allows to get rid of chip-specific endpoint matching code from
epautoconf.
If gadget has set 'ep_match' callback we prefer to call it first, and
if it fails to find matching endpoint, then we try to use default matching
algorithm.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 6 ++++++
include/linux/usb/gadget.h | 3 +++
2 files changed, 9 insertions(+)
From: Robert Baldyga <hidden> Date: 2015-07-15 06:38:19
As function ep_matches() is used to match endpoint with usb descriptor it's
highly unintuitive that it modifies endpoint and descriptor structures fields.
This patch moves code configuring ep and desc from ep_matches() to
usb_ep_autoconfig_ss(), so now function ep_matches() does nothing more than
its name suggests.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 66 +++++++++++++++++++++--------------------
1 file changed, 34 insertions(+), 32 deletions(-)
From: Robert Baldyga <hidden> Date: 2015-07-15 06:38:26
Move ep_matches() function to udc-core and rename it to
usb_gadget_ep_match_desc(). This function can be used by UDC drivers
in 'match_ep' callback to avoid writing lots of repetitive code.
Replace all calls of ep_matches() with usb_gadget_ep_match_desc().
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 95 +++++----------------------------------
drivers/usb/gadget/udc/udc-core.c | 69 ++++++++++++++++++++++++++++
include/linux/usb/gadget.h | 8 ++++
3 files changed, 88 insertions(+), 84 deletions(-)
@@ -22,82 +22,6 @@#include"gadget_chips.h"-staticint-ep_matches(-structusb_gadget*gadget,-structusb_ep*ep,-structusb_endpoint_descriptor*desc,-structusb_ss_ep_comp_descriptor*ep_comp-)-{-u8type;-u16max;-intnum_req_streams=0;--/* endpoint already claimed? */-if(ep->claimed)-return0;--type=usb_endpoint_type(desc);-max=0x7ff&usb_endpoint_maxp(desc);--if(usb_endpoint_dir_in(desc)&&!ep->caps.dir_in)-return0;-elseif(!ep->caps.dir_out)-return0;--if(max>ep->maxpacket_limit)-return0;--/* "high bandwidth" works only at high speed */-if(!gadget_is_dualspeed(gadget)&&usb_endpoint_maxp(desc)&(3<<11))-return0;--switch(type){-caseUSB_ENDPOINT_XFER_CONTROL:-/* only support ep0 for portable CONTROL traffic */-return0;-caseUSB_ENDPOINT_XFER_ISOC:-if(!ep->caps.type_iso)-return0;-/* ISO: limit 1023 bytes full speed,-*1024high/superspeed-*/-if(!gadget_is_dualspeed(gadget)&&max>1023)-return0;-break;-caseUSB_ENDPOINT_XFER_BULK:-if(!ep->caps.type_bulk)-return0;-if(ep_comp&&gadget_is_superspeed(gadget)){-/* Get the number of required streams from the-*EPcompaniondescriptorandseeiftheEP-*matchesit-*/-num_req_streams=ep_comp->bmAttributes&0x1f;-if(num_req_streams>ep->max_streams)-return0;-}-break;-caseUSB_ENDPOINT_XFER_INT:-/* Bulk endpoints handle interrupt transfers,-*exceptthetoggle-quirkyiso-synchkind-*/-if(!ep->caps.type_int&&!ep->caps.type_bulk)-return0;-/* INT: limit 64 bytes full speed,-*1024high/superspeed-*/-if(!gadget_is_dualspeed(gadget)&&max>64)-return0;-break;-}--/* MATCH!! */--return1;-}-staticstructusb_ep*find_ep(structusb_gadget*gadget,constchar*name){
@@ -180,10 +104,12 @@ struct usb_ep *usb_ep_autoconfig_ss(if(type==USB_ENDPOINT_XFER_INT){/* ep-e, ep-f are PIO with only 64 byte fifos */ep=find_ep(gadget,"ep-e");-if(ep&&ep_matches(gadget,ep,desc,ep_comp))+if(ep&&usb_gadget_ep_match_desc(gadget,+ep,desc,ep_comp))gotofound_ep;ep=find_ep(gadget,"ep-f");-if(ep&&ep_matches(gadget,ep,desc,ep_comp))+if(ep&&usb_gadget_ep_match_desc(gadget,+ep,desc,ep_comp))gotofound_ep;}
@@ -191,20 +117,21 @@ struct usb_ep *usb_ep_autoconfig_ss(snprintf(name,sizeof(name),"ep%d%s",usb_endpoint_num(desc),usb_endpoint_dir_in(desc)?"in":"out");ep=find_ep(gadget,name);-if(ep&&ep_matches(gadget,ep,desc,ep_comp))+if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;}elseif(gadget_is_goku(gadget)){if(USB_ENDPOINT_XFER_INT==type){/* single buffering is enough */ep=find_ep(gadget,"ep3-bulk");-if(ep&&ep_matches(gadget,ep,desc,ep_comp))+if(ep&&usb_gadget_ep_match_desc(gadget,+ep,desc,ep_comp))gotofound_ep;}elseif(USB_ENDPOINT_XFER_BULK==type&&(USB_DIR_IN&desc->bEndpointAddress)){/* DMA may be available */ep=find_ep(gadget,"ep2-bulk");-if(ep&&ep_matches(gadget,ep,desc,-ep_comp))+if(ep&&usb_gadget_ep_match_desc(gadget,+ep,desc,ep_comp))gotofound_ep;}
@@ -223,14 +150,14 @@ struct usb_ep *usb_ep_autoconfig_ss(ep=find_ep(gadget,"ep2out");}elseep=NULL;-if(ep&&ep_matches(gadget,ep,desc,ep_comp))+if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;#endif}/* Second, look at endpoints until an unclaimed one looks usable */list_for_each_entry(ep,&gadget->ep_list,ep_list){-if(ep_matches(gadget,ep,desc,ep_comp))+if(usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;}
@@ -129,6 +129,75 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);/* ------------------------------------------------------------------------- */+intusb_gadget_ep_match_desc(structusb_gadget*gadget,+structusb_ep*ep,structusb_endpoint_descriptor*desc,+structusb_ss_ep_comp_descriptor*ep_comp)+{+u8type;+u16max;+intnum_req_streams=0;++/* endpoint already claimed? */+if(ep->claimed)+return0;++type=usb_endpoint_type(desc);+max=0x7ff&usb_endpoint_maxp(desc);++if(usb_endpoint_dir_in(desc)&&!ep->caps.dir_in)+return0;+elseif(!ep->caps.dir_out)+return0;++if(max>ep->maxpacket_limit)+return0;++/* "high bandwidth" works only at high speed */+if(!gadget_is_dualspeed(gadget)&&usb_endpoint_maxp(desc)&(3<<11))+return0;++switch(type){+caseUSB_ENDPOINT_XFER_CONTROL:+/* only support ep0 for portable CONTROL traffic */+return0;+caseUSB_ENDPOINT_XFER_ISOC:+if(!ep->caps.type_iso)+return0;+/* ISO: limit 1023 bytes full speed, 1024 high/super speed */+if(!gadget_is_dualspeed(gadget)&&max>1023)+return0;+break;+caseUSB_ENDPOINT_XFER_BULK:+if(!ep->caps.type_bulk)+return0;+if(ep_comp&&gadget_is_superspeed(gadget)){+/* Get the number of required streams from the+*EPcompaniondescriptorandseeiftheEP+*matchesit+*/+num_req_streams=ep_comp->bmAttributes&0x1f;+if(num_req_streams>ep->max_streams)+return0;+}+break;+caseUSB_ENDPOINT_XFER_INT:+/* Bulk endpoints handle interrupt transfers,+*exceptthetoggle-quirkyiso-synchkind+*/+if(!ep->caps.type_int&&!ep->caps.type_bulk)+return0;+/* INT: limit 64 bytes full speed, 1024 high/super speed */+if(!gadget_is_dualspeed(gadget)&&max>64)+return0;+break;+}++return1;+}+EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);++/* ------------------------------------------------------------------------- */+staticvoidusb_gadget_state_work(structwork_struct*work){structusb_gadget*gadget=work_to_gadget(work);
@@ -1079,6 +1079,14 @@ extern void usb_gadget_giveback_request(struct usb_ep *ep,/*-------------------------------------------------------------------------*/+/* utility to check if endpoint caps match descriptor needs */++externintusb_gadget_ep_match_desc(structusb_gadget*gadget,+structusb_ep*ep,structusb_endpoint_descriptor*desc,+structusb_ss_ep_comp_descriptor*ep_comp);++/*-------------------------------------------------------------------------*/+/* utility to update vbus status for udc core, it may be scheduled */externvoidusb_udc_vbus_handler(structusb_gadget*gadget,boolstatus);
From: Robert Baldyga <hidden> Date: 2015-07-15 06:38:41
Add 'match_ep' callback to utilize chip-specific knowledge in endpoint matching
process. Function does the same that was done by chip-specific code inside
of epautoconf. Now this code can be removed from there to separate generic code
from platform specific logic.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 20 ++------------------
drivers/usb/gadget/udc/goku_udc.c | 25 +++++++++++++++++++++++++
2 files changed, 27 insertions(+), 18 deletions(-)
@@ -86,24 +86,8 @@ struct usb_ep *usb_ep_autoconfig_ss(/* First, apply chip-specific "best usage" knowledge.*Thismightmakeagoodusb_gadget_opshook...*/-if(gadget_is_goku(gadget)){-if(USB_ENDPOINT_XFER_INT==type){-/* single buffering is enough */-ep=gadget_find_ep_by_name(gadget,"ep3-bulk");-if(ep&&usb_gadget_ep_match_desc(gadget,-ep,desc,ep_comp))-gotofound_ep;-}elseif(USB_ENDPOINT_XFER_BULK==type-&&(USB_DIR_IN&desc->bEndpointAddress)){-/* DMA may be available */-ep=gadget_find_ep_by_name(gadget,"ep2-bulk");-if(ep&&usb_gadget_ep_match_desc(gadget,-ep,desc,ep_comp))-gotofound_ep;-}-#ifdef CONFIG_BLACKFIN-}elseif(gadget_is_musbhdrc(gadget)){+if(gadget_is_musbhdrc(gadget)){if((USB_ENDPOINT_XFER_BULK==type)||(USB_ENDPOINT_XFER_ISOC==type)){if(USB_DIR_IN&desc->bEndpointAddress)
@@ -119,8 +103,8 @@ struct usb_ep *usb_ep_autoconfig_ss(ep=NULL;if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;-#endif}+#endif/* Second, look at endpoints until an unclaimed one looks usable */list_for_each_entry(ep,&gadget->ep_list,ep_list){
@@ -990,6 +990,30 @@ static int goku_get_frame(struct usb_gadget *_gadget)return-EOPNOTSUPP;}+staticstructusb_ep*goku_match_ep(structusb_gadget*g,+structusb_endpoint_descriptor*desc,+structusb_ss_ep_comp_descriptor*ep_comp)+{+structgoku_udc*dev=to_goku_udc(g);+structusb_ep*ep;+u8type=usb_endpoint_type(desc);++if(type==USB_ENDPOINT_XFER_INT){+/* single buffering is enough */+ep=&dev->ep[3].ep;+if(ep&&usb_gadget_ep_match_desc(g,ep,desc,ep_comp))+returnep;+}elseif(type==USB_ENDPOINT_XFER_BULK+&&usb_endpoint_dir_in(desc)){+/* DMA may be available */+ep=&dev->ep[2].ep;+if(ep&&usb_gadget_ep_match_desc(g,ep,desc,ep_comp))+returnep;+}++returnNULL;+}+staticintgoku_udc_start(structusb_gadget*g,structusb_gadget_driver*driver);staticintgoku_udc_stop(structusb_gadget*g);
@@ -998,6 +1022,7 @@ static const struct usb_gadget_ops goku_ops = {.get_frame=goku_get_frame,.udc_start=goku_udc_start,.udc_stop=goku_udc_stop,+.match_ep=goku_match_ep,// no remote wakeup// not selfpowered};
From: Robert Baldyga <hidden> Date: 2015-07-15 06:38:43
Add 'match_ep' callback to utilize chip-specific knowledge in endpoint matching
process. Function does the same that was done by chip-specific code inside
of epautoconf. Now this code can be removed from there to separate generic code
from platform specific logic.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 23 +----------------------
drivers/usb/gadget/udc/net2280.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+), 22 deletions(-)
@@ -86,28 +86,7 @@ struct usb_ep *usb_ep_autoconfig_ss(/* First, apply chip-specific "best usage" knowledge.*Thismightmakeagoodusb_gadget_opshook...*/-if(gadget_is_net2280(gadget)){-charname[8];--if(type==USB_ENDPOINT_XFER_INT){-/* ep-e, ep-f are PIO with only 64 byte fifos */-ep=gadget_find_ep_by_name(gadget,"ep-e");-if(ep&&usb_gadget_ep_match_desc(gadget,-ep,desc,ep_comp))-gotofound_ep;-ep=gadget_find_ep_by_name(gadget,"ep-f");-if(ep&&usb_gadget_ep_match_desc(gadget,-ep,desc,ep_comp))-gotofound_ep;-}--/* USB3380: use same address for usb and hardware endpoints */-snprintf(name,sizeof(name),"ep%d%s",usb_endpoint_num(desc),-usb_endpoint_dir_in(desc)?"in":"out");-ep=gadget_find_ep_by_name(gadget,name);-if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))-gotofound_ep;-}elseif(gadget_is_goku(gadget)){+if(gadget_is_goku(gadget)){if(USB_ENDPOINT_XFER_INT==type){/* single buffering is enough */ep=gadget_find_ep_by_name(gadget,"ep3-bulk");
@@ -1533,6 +1533,36 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)return0;}+staticstructusb_ep*net2280_match_ep(structusb_gadget*_gadget,+structusb_endpoint_descriptor*desc,+structusb_ss_ep_comp_descriptor*ep_comp)+{+charname[8];+structusb_ep*ep;+u8type;++type=usb_endpoint_type(desc);++if(type==USB_ENDPOINT_XFER_INT){+/* ep-e, ep-f are PIO with only 64 byte fifos */+ep=gadget_find_ep_by_name(_gadget,"ep-e");+if(ep&&usb_gadget_ep_match_desc(_gadget,ep,desc,ep_comp))+returnep;+ep=gadget_find_ep_by_name(_gadget,"ep-f");+if(ep&&usb_gadget_ep_match_desc(_gadget,ep,desc,ep_comp))+returnep;+}++/* USB3380: use same address for usb and hardware endpoints */+snprintf(name,sizeof(name),"ep%d%s",usb_endpoint_num(desc),+usb_endpoint_dir_in(desc)?"in":"out");+ep=gadget_find_ep_by_name(_gadget,name);+if(ep&&usb_gadget_ep_match_desc(_gadget,ep,desc,ep_comp))+returnep;++returnNULL;+}+staticintnet2280_start(structusb_gadget*_gadget,structusb_gadget_driver*driver);staticintnet2280_stop(structusb_gadget*_gadget);
From: Robert Baldyga <hidden> Date: 2015-07-15 06:38:50
Add 'match_ep' callback to utilize chip-specific knowledge in endpoint matching
process. Function does the same that was done by chip-specific code inside
of epautoconf. Now this code can be removed from there to separate generic code
from platform specific logic.
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 23 -----------------------
drivers/usb/musb/musb_gadget.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 23 deletions(-)
From: Robert Baldyga <hidden> Date: 2015-07-15 06:39:57
Move find_ep() function to gadget.h, rename it to gadget_find_ep_by_name()
and make it static inline. It can be used in UDC drivers, especially in
'match_ep' callback after moving chip-specific endpoint matching logic from
epautoconf to UDC drivers.
Replace all calls of find_ep() function with gadget_find_ep_by_name().
Signed-off-by: Robert Baldyga <redacted>
---
drivers/usb/gadget/epautoconf.c | 30 +++++++++---------------------
include/linux/usb/gadget.h | 18 ++++++++++++++++++
2 files changed, 27 insertions(+), 21 deletions(-)
@@ -103,11 +91,11 @@ struct usb_ep *usb_ep_autoconfig_ss(if(type==USB_ENDPOINT_XFER_INT){/* ep-e, ep-f are PIO with only 64 byte fifos */-ep=find_ep(gadget,"ep-e");+ep=gadget_find_ep_by_name(gadget,"ep-e");if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;-ep=find_ep(gadget,"ep-f");+ep=gadget_find_ep_by_name(gadget,"ep-f");if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;
@@ -116,20 +104,20 @@ struct usb_ep *usb_ep_autoconfig_ss(/* USB3380: use same address for usb and hardware endpoints */snprintf(name,sizeof(name),"ep%d%s",usb_endpoint_num(desc),usb_endpoint_dir_in(desc)?"in":"out");-ep=find_ep(gadget,name);+ep=gadget_find_ep_by_name(gadget,name);if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;}elseif(gadget_is_goku(gadget)){if(USB_ENDPOINT_XFER_INT==type){/* single buffering is enough */-ep=find_ep(gadget,"ep3-bulk");+ep=gadget_find_ep_by_name(gadget,"ep3-bulk");if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;}elseif(USB_ENDPOINT_XFER_BULK==type&&(USB_DIR_IN&desc->bEndpointAddress)){/* DMA may be available */-ep=find_ep(gadget,"ep2-bulk");+ep=gadget_find_ep_by_name(gadget,"ep2-bulk");if(ep&&usb_gadget_ep_match_desc(gadget,ep,desc,ep_comp))gotofound_ep;
@@ -2018,12 +2018,23 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)usb_ep_set_maxpacket_limit(&ep->ep,MAX_CTRL_PL_SIZE);ep->bytes_per_buffer=MAX_CTRL_PL_SIZE;++ep->ep.caps.type_control=true;}else{usb_ep_set_maxpacket_limit(&ep->ep,(u16)maxplimit);list_add_tail(&ep->ep.ep_list,&dev->gadget.ep_list);++ep->ep.caps.type_iso=true;+ep->ep.caps.type_bulk=true;+ep->ep.caps.type_int=true;}list_add_tail(&ep->ep_list,&dev->ep_list);+if(is_in)+ep->ep.caps.dir_in=true;+else+ep->ep.caps.dir_out=true;+ep->tailbuf=dma_alloc_coherent(dev->dev,ep->ep.maxpacket_limit,&ep->tailbuf_paddr,GFP_ATOMIC);if(!ep->tailbuf)
From: Krzysztof Opasiak <hidden> Date: 2015-07-20 14:43:29
On 07/15/2015 08:31 AM, Robert Baldyga wrote:
So far it was necessary for usb functions to set ep->driver_data in
endpoint obtained from autoconfig to non-null value, to indicate that
endpoint is claimed by function (in autoconfig it was checked if endpoint
has set this field to non-null value, and if it has, it was assumed that
it is claimed). It could cause bugs becouse if some function doesn't
s/becouse/because
Best regards,
--
Krzysztof Opasiak
Samsung R&D Institute Poland
Samsung Electronics
In all previous patches you set both dir_in and dir_out to true for ep0
but in this patch you don't do this. Is there some reason for this or
it's just a mistake?
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
/* need to set ep->ep.maxpacket and set Default Configuration?*/
usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
Best Regards,
--
Krzysztof Opasiak
Samsung R&D Institute Poland
Samsung Electronics
In all previous patches you set both dir_in and dir_out to true for ep0
but in this patch you don't do this. Is there some reason for this or
it's just a mistake?
Most of UDC drivers we have single instance of ep0 for both directions,
but this one has two separate unidirectional ep0in and ep0out.
quoted
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
/* need to set ep->ep.maxpacket and set Default
Configuration?*/
usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);