Date: Wed, 29 Jul 2009 08:41:45 GMT From: Sylvestre Gallon <syl@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 166722 for review Message-ID: <200907290841.n6T8fjqI025079@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=166722 Change 166722 by syl@syl_twoflowers on 2009/07/29 08:41:13 Implement test and proposition part of the report. Affected files ... .. //depot/projects/soc2009/syl_usb/hps_report/DifferentAPI.tex#2 edit .. //depot/projects/soc2009/syl_usb/hps_report/GenericCode.tex#3 edit .. //depot/projects/soc2009/syl_usb/hps_report/Proposition.tex#2 edit .. //depot/projects/soc2009/syl_usb/hps_report/SomeTests.tex#2 edit .. //depot/projects/soc2009/syl_usb/hps_report/report.tex#2 edit Differences ... ==== //depot/projects/soc2009/syl_usb/hps_report/DifferentAPI.tex#2 (text+ko) ==== @@ -1,7 +1,7 @@ \chapter{Differents APIs} Only three portable Operating System have a USB Function Stack. In this chapter we will focus on the different API for Adding a -new Device Controler Interface on Linux Windows CE and FreeBSD. +new Device Controler Interface on Linux, Windows CE and FreeBSD. \section{Linux} @@ -162,7 +162,7 @@ The code is in dev/usb/usb\_controller.h. FreeBSD use the same structure for both Host and Device Controllers Interfaces. An USB DCI must implement an usb\_bus\_methods structure. These - structure is share between DCI and HCI. + structure are shared between DCI and HCI. \begin{lstlisting} struct usb_bus_methods { @@ -217,7 +217,7 @@ }; \end{lstlisting} - Concerning endpoint FreeBSD us usb\_pipe\_methods structure. + Concerning endpoint FreeBSD use usb\_pipe\_methods structure. \begin{lstlisting} /* @@ -240,8 +240,10 @@ void *info; }; \end{lstlisting} - For describing possibilities of the differennt endpoints contain by the xCI - FreeBSD have the structure usb\_hw\_ep\_profile. + + For describing possibilities of the different endpoints contained + by the xCI FreeBSD have the structure usb\_hw\_ep\_profile. + \begin{lstlisting} /* * The following structure keeps information about what a hardware USB ==== //depot/projects/soc2009/syl_usb/hps_report/GenericCode.tex#3 (text+ko) ==== @@ -10,8 +10,9 @@ diff -uNp at91dci.c s3c24xxdci.c \end{lstlisting} - We can see that only few function are different from a driver to another. - The code different is specific to the Hardware. Lets us describes this functions : + We can see that only few functions are different from a driver to another. + The different code is most of the time Hardware specific. Lets us describes + these functions : \section{Hardware Dependant Code} @@ -56,11 +57,13 @@ - xxxdci\_start\_standard\_chain - Concerning clock\_on, clock\_off, pull\_up, pull\_down, wakeup\_peer can be a little bit - factorised. A big part of this function do not move we can create a generic function called - directly after or before Hardware changes. Perhaps there is also something that could be - factorised in xxxdci\_uninit if there are not other possible access that interrupt disabling - in it. + Clock\_on, clock\_off, pull\_up, pull\_down, wakeup\_peer can be + factorised. A big part of this function do not move and we can create + a generic function called directly after or before Hardware changes. + + Perhaps there is also something that could be factorised in xxxdci\_uninit + if there are not other possible access to the Hardware that interrupt disabling + in this function. There are pehaps something to do with xxxdci\_device\_done and xxxdci\_start\_standard\_chain beacuse the only hardware code present int this function just enable Endpoint interrupt. @@ -95,3 +98,68 @@ - xxxdci\_xfer\_do\_fifo + xxdci\_ep\_init and xxxdci\_xfer\_setup are more or less generic. The only change we can have + between 2 controller afecting this function is the support or no of asynchronous endpoints. + This problem could be resolved if we parse xxxdci\_ep\_profile to know if the device support + asynchronous endpoints. + + All the HUB descriptor code are the same between the controller drivers. We can easily factorise it + without performance modification. + + There is some big change on the way to handle basic control request like GET\_STATUS etc. Linux and + Wince seems to handle That on a generic file who perform basic request during the configuration process. + In FreeBSD all these functionality are present in the controlleur code in the function roothub\_exec. + This function looks like the same on each controller. + + There is something for factorising the code for xxxdci\_device\_XXX\_methods. I have implemented it + on s3c24xxxdci driver this way : + + \begin{lstlisting} + /* + * s3c24xxdci ctrl/bulk/intr support + */ + + static void + s3c24dci_device_dummy(struct usb_xfer *xfer) + { + return ; + } + + static void + s3c24dci_device_xxx_start(struct usb_xfer *xfer) + { + s3c24dci_setup_standard_chain(xfer); + s3c24dci_start_standard_chain(xfer); + return ; + } + + static void + s3c24dci_device_xxx_close(struct usb_xfer *xfer) + { + s3c24dci_device_done(xfer, USB_ERR_CANCELLED); + return ; + } + + struct usb_pipe_methods s3c24dci_device_ctrl_methods = { + .open = s3c24dci_device_dummy, + .enter = s3c24dci_device_dummy, + .close = s3c24dci_device_xxx_close, + .start = s3c24dci_device_xxx_start, + }; + + struct usb_pipe_methods s3c24dci_device_bulk_methods = { + .open = s3c24dci_device_dummy, + .enter = s3c24dci_device_dummy, + .close = s3c24dci_device_xxx_close, + .start = s3c24dci_device_xxx_start, + }; + + struct usb_pipe_methods s3c24dci_device_intr_methods = { + .open = s3c24dci_device_dummy, + .enter = s3c24dci_device_dummy, + .close = s3c24dci_device_xxx_close, + .start = s3c24dci_device_xxx_start, + }; + \end{lstlisting} + + All the others functions seems to be generic. ==== //depot/projects/soc2009/syl_usb/hps_report/Proposition.tex#2 (text+ko) ==== @@ -1,1 +1,37 @@ \chapter{What can be done ?} + \section{HUB Descriptor} + + A good solution to factorise the USB descriptors is to add + another entry in the directory for HUB descripors. + /src/sys/dev/usb/template/ + + We implement this file like this one : + + /src/sys/dev/usb/template/usb\_template\_cdce.c + + \section{xxxdci\_device\_XXX\_methods} + + We can factorize some code on each driver with simply adding in a .h + something like that: + + \begin{lstlisting} +static inline void +dci_device_dummy ( struct usb_xfer * xfer ) +{ + return ; +} + \end{lstlisting} + + With this Change we can easily implement the xxxdci\_device\_XXX\_methods + with less code following the mothod used for the s3c2xxdci implementation. + + \section{roothub} + We can Create A GenericRootHub function who will takes a + struct with callback as parameters. + + It will permit the driver to implement roothub\_exec or call + GenericRootHub. + + \section{other generic functions} + + I Have no idea now how to factorise them, but any advices are welcome ! ==== //depot/projects/soc2009/syl_usb/hps_report/SomeTests.tex#2 (text+ko) ==== @@ -1,2 +1,162 @@ \chapter{Test} - \section{callback versus switch} + +Here is the result of some test used for finding the best implementation +for the Improvement into USB. + + \section{ops structure Versus Simple call} + + \begin{lstlisting} + +#include <stdio.h> + +struct fops { + void (*f)(int i); +}; + +void +toto(int i) +{ + printf("%i\n", i); +} + +struct fops fops = + { + .f = &toto + }; + +int main() +{ + __asm("nop"); + __asm("nop"); + __asm("nop"); + __asm("nop"); + toto(42); + __asm("nop"); + __asm("nop"); + __asm("nop"); + __asm("nop"); + fops.f(42); +} + \end{lstlisting} + + Here is the assembly done by this code for x86. + + \begin{lstlisting} + 80483d4: 90 nop + 80483d5: 90 nop + 80483d6: 90 nop + 80483d7: 90 nop + 80483d8: c7 04 24 2a 00 00 00 movl $0x2a,(%esp) + 80483df: e8 c0 ff ff ff call 80483a4 <toto> + 80483e4: 90 nop + 80483e5: 90 nop + 80483e6: 90 nop + 80483e7: 90 nop + 80483e8: a1 e0 95 04 08 mov 0x80495e0,%eax + 80483ed: c7 04 24 2a 00 00 00 movl $0x2a,(%esp) + 80483f4: ff d0 call *%eax + \end{lstlisting} + + Here is the assembly done by this code for armv4i + + \begin{lstlisting} + 84ac: e1a00000 nop (mov r0,r0) + 84b0: e1a00000 nop (mov r0,r0) + 84b4: e1a00000 nop (mov r0,r0) + 84b8: e1a00000 nop (mov r0,r0) + 84bc: e3a0002a mov r0, #42 ; 0x2a + 84c0: ebffffe5 bl 845c <toto> + 84c4: e1a00000 nop (mov r0,r0) + 84c8: e1a00000 nop (mov r0,r0) + 84cc: e1a00000 nop (mov r0,r0) + 84d0: e1a00000 nop (mov r0,r0) + 84d4: e59f3028 ldr r3, [pc, #40] ; 8504 <main+0x78> + 84d8: e5933000 ldr r3, [r3] + 84dc: e3a0002a mov r0, #42 ; 0x2a + 84e0: e1a0e00f mov lr, pc + 84e4: e12fff13 bx r3 + \end{lstlisting} + + \section{Single demultiplex vs multiple demultiplex} + + Finally there is no great difference between callbacks and simple call. + + \begin{lstlisting} +int +switcha(int toto) +{ + switch(toto) { + case 3: + break ; + case 4: + break ; + } + +} + +int +switchb(int toto) +{ + switch(toto) { + case 5: + break ; + case 6: + break ; + } +} + +int +multipleswitch(int toto) +{ + __asm("nop"); + __asm("nop"); + switch(toto) { + case 1: + switcha(toto -2 ); + break; + case 2: + switchb(toto - 4); + break; + } + __asm("nop"); + __asm("nop"); +} + +int +singleswitch(int toto) +{ + __asm("nop"); + __asm("nop"); + switch (toto) { + case 1: + switch (toto - 2) { + case 3: + break ; + case 4: + break ; + } + break ; + case 2: + switch(toto -4) { + case 5: + break ; + case 6: + break ; + } + break ; + } + __asm("nop"); + __asm("nop"); +} + +int +main() +{ + singleswitch(a); + singleswitch(b); +} + \end{lstlisting} + + With this code gcc dump exactly the same switch function that do nothing. + But for the multipleswitch the functionn switcha and switchb are also generated. + ==== //depot/projects/soc2009/syl_usb/hps_report/report.tex#2 (text+ko) ====
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907290841.n6T8fjqI025079>
