Re: Small example program shut down urtwn

2016-09-05 Thread Adrian Chadd
hm, interesting! I wonder if urtwn and/or usb is missing some bus
barriers for ARM or something?


-a


On 4 September 2016 at 14:18, Otacílio  wrote:
> Dears
>
> I wrote these two small programs to help debug a problem that I think I have
> found when using urtwn driver in a baglebone black. The problem is 100%
> reproducible.
>
> In a server machine I run:
>
> serverUDP 2508
>
> In beaglebone black I run:
>
> ./clientUDP servername 2508 9216 0
>
> All the times, after some packages be sent the urtwn interface do not
> respond from ping and stops send others packages. Some times this error
> message appears:
>
> % urtwn0: device timeout
>
> I have tested with RTL8192CU and RTL8188CUS
>
> The problem do no occurs in my notebook.
>
> Following the server and client
>
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
>
> #define BUFFER_LEN1024*1024
>
> void diep(char *s)
> {
> perror(s);
> exit(1);
> }
>
> int main(int argc, char **argv)
> {
> int lidos;
> struct sockaddr_in si_me, si_other;
> int s, i, slen=sizeof(si_other);
> char buf[BUFFER_LEN];
> int aux;
>
> if(argc != 2){
> fprintf(stderr, "Voce deve usar %s \n", argv[0]);
> exit(1);
> }
>
> if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
> diep("socket");
>
> memset((char *) _me, 0, sizeof(si_me));
> si_me.sin_family = AF_INET;
> si_me.sin_port = htons(strtol(argv[1], (char **)NULL, 10));
> si_me.sin_addr.s_addr = htonl(INADDR_ANY);
> if (bind(s, (struct sockaddr *)_me, sizeof(si_me))==-1)
> diep("bind");
>
> i = 1;
> do {
> if ((lidos = recvfrom(s, buf, BUFFER_LEN, 0, (struct sockaddr
> *)_other, (socklen_t *)))==-1)
> diep("recvfrom()");
> aux = ntohl(*(int*)[0]);
> printf("Perdidos %d pacotes (%0.2f%%)\n", aux - i, 100*((float)(aux
> - i))/((float)aux));
> printf("Sequencia %d Recebidos %d bytes\n", aux, lidos);
> i++;
> }while(lidos>0);
>
> close(s);
> return 0;
> }
>
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
>
> #define SOCKET_ERROR-1
> #define INVALID_SOCKET-1
>
> #define SRV_IP "127.0.0.1"
>
> void diep(char *s)
> {
> perror(s);
> exit(1);
> }
>
>
> int main(int argc, char **argv)
> {
> struct sockaddr_in si_other;
> int s, i, slen=sizeof(si_other);
> char *buf;
> int tamanho;
> int npack;
> struct addrinfo *result = NULL,
> *ptr = NULL,
> hints;
> int iResult, aux;
> fd_set fdset;
>
> if(argc != 5){
> fprintf(stderr,"Voce deve usar %s de pacotes>\n", argv[0]);
> exit(1);
> }
>
> tamanho= (int)strtol(argv[3], (char **)NULL, 10);
> npack= (int)strtol(argv[4], (char **)NULL, 10);
>
> buf = malloc(tamanho);
>
> bzero(, sizeof(hints));
> hints.ai_family = AF_UNSPEC;
> hints.ai_socktype = SOCK_DGRAM;
> hints.ai_protocol = IPPROTO_UDP;
>
> iResult = getaddrinfo(argv[1], argv[2], , );
> if ( iResult != 0 ) {
> printf("getaddrinfo failed with error: %d\n", iResult);
> return 1;
> }
>
> // Attempt to connect to an address until one succeeds
> for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
>
> // Create a SOCKET for connecting to server
> s = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
> if (s < 0){
> perror("socket");
> return 1;
>}
>
>// Connect to server.
>iResult = connect(s, ptr->ai_addr, (int)ptr->ai_addrlen);
>if (iResult == SOCKET_ERROR) {
> close(s);
> s = INVALID_SOCKET;
>continue;
>}
>
>break;
> }
>
> freeaddrinfo(result);
> FD_ZERO();
> FD_SET(s, );
> for (i=1; i<=npack || npack==0; i++) {
> aux = htonl(i);
> memcpy([0], , sizeof(aux));
> aux = htonl(npack);
> memcpy([0+sizeof(i)], , sizeof(aux));
> do{
> if(select(s+1, NULL, , NULL, NULL )<0)
> diep("select()");
> }while(!FD_ISSET(s, ));
> if (send(s, buf, tamanho, 0)==-1)
> diep("sendto()");
> }
> printf("Enviados %d pacotes de %d bytes\n", npack, tamanho);
>
> close(s);
> return 0;
> }
> ___
> freebsd-wireless@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
> To unsubscribe, send any mail to "freebsd-wireless-unsubscr...@freebsd.org"
___
freebsd-wireless@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
To unsubscribe, send any mail to 

Re: Deadlock between device_detach() and usbd_do_request_flags()

2016-09-05 Thread Hans Petter Selasky

On 09/05/16 12:21, Andriy Voskoboinyk wrote:

Mon, 05 Sep 2016 12:10:34 +0300 було написано Hans Petter Selasky
:

Works fine, thanks!

P.S. Reliable test case:
1) ifconfig wlan1 create wlandev 
2) wpa_supplicant -i wlan1 -c /etc/wpa_supplicant.conf &
   * wait for CTRL-EVENT-CONNECTED event
3) usbconfig -d . power_off


Hi,

Can you test the attached patch? Does it solve your issue?

--HPS




FYI:

https://svnweb.freebsd.org/changeset/base/305421

--HPS
___
freebsd-wireless@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
To unsubscribe, send any mail to "freebsd-wireless-unsubscr...@freebsd.org"

Re: Deadlock between device_detach() and usbd_do_request_flags()

2016-09-05 Thread Andriy Voskoboinyk
Mon, 05 Sep 2016 12:10:34 +0300 було написано Hans Petter Selasky  
:


Works fine, thanks!

P.S. Reliable test case:
1) ifconfig wlan1 create wlandev 
2) wpa_supplicant -i wlan1 -c /etc/wpa_supplicant.conf &
   * wait for CTRL-EVENT-CONNECTED event
3) usbconfig -d . power_off


Hi,

Can you test the attached patch? Does it solve your issue?

--HPS

___
freebsd-wireless@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
To unsubscribe, send any mail to "freebsd-wireless-unsubscr...@freebsd.org"

Re: Deadlock between device_detach() and usbd_do_request_flags()

2016-09-05 Thread Hans Petter Selasky

Hi,

Can you test the attached patch? Does it solve your issue?

--HPS
Index: sys/dev/usb/usb_device.c
===
--- sys/dev/usb/usb_device.c	(revision 304569)
+++ sys/dev/usb/usb_device.c	(working copy)
@@ -1585,6 +1585,7 @@
 	/* initialise our SX-lock */
 	sx_init_flags(>enum_sx, "USB config SX lock", SX_DUPOK);
 	sx_init_flags(>sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS);
+	sx_init_flags(>ctrl_sx, "USB control transfer SX lock", SX_DUPOK);
 
 	cv_init(>ctrlreq_cv, "WCTRL");
 	cv_init(>ref_cv, "UGONE");
@@ -2195,6 +2196,7 @@
 	
 	sx_destroy(>enum_sx);
 	sx_destroy(>sr_sx);
+	sx_destroy(>ctrl_sx);
 
 	cv_destroy(>ctrlreq_cv);
 	cv_destroy(>ref_cv);
Index: sys/dev/usb/usb_device.h
===
--- sys/dev/usb/usb_device.h	(revision 304569)
+++ sys/dev/usb/usb_device.h	(working copy)
@@ -183,6 +183,7 @@
 	struct usb_udev_msg cs_msg[2];
 	struct sx enum_sx;
 	struct sx sr_sx;
+  	struct sx ctrl_sx;
 	struct mtx device_mtx;
 	struct cv ctrlreq_cv;
 	struct cv ref_cv;
Index: sys/dev/usb/usb_request.c
===
--- sys/dev/usb/usb_request.c	(revision 304569)
+++ sys/dev/usb/usb_request.c	(working copy)
@@ -418,7 +418,6 @@
 	uint16_t length;
 	uint16_t temp;
 	uint16_t acttemp;
-	uint8_t do_unlock;
 
 	if (timeout < 50) {
 		/* timeout is too small */
@@ -460,16 +459,16 @@
 	}
 
 	/*
-	 * Grab the USB device enumeration SX-lock serialization is
-	 * achieved when multiple threads are involved:
+	 * Serialize access to this function:
 	 */
-	do_unlock = usbd_enum_lock(udev);
+	sx_xlock(>ctrl_sx);
 
 	/*
 	 * We need to allow suspend and resume at this point, else the
 	 * control transfer will timeout if the device is suspended!
 	 */
-	usbd_sr_unlock(udev);
+	if (usbd_enum_is_locked(udev))
+		usbd_sr_unlock(udev);
 
 	hr_func = usbd_get_hr_func(udev);
 
@@ -713,10 +712,10 @@
 	USB_XFER_UNLOCK(xfer);
 
 done:
-	usbd_sr_lock(udev);
+	sx_xunlock(>ctrl_sx);
 
-	if (do_unlock)
-		usbd_enum_unlock(udev);
+	if (usbd_enum_is_locked(udev))
+		usbd_sr_lock(udev);
 
 	if ((mtx != NULL) && (mtx != ))
 		mtx_lock(mtx);
___
freebsd-wireless@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
To unsubscribe, send any mail to "freebsd-wireless-unsubscr...@freebsd.org"

Re: Deadlock between device_detach() and usbd_do_request_flags()

2016-09-05 Thread Hans Petter Selasky

On 09/05/16 09:53, Hans Petter Selasky wrote:


Hi,

I think the right solution is to let usbd_do_request_flags() use its own
SX lock for synchronization, instead of re-using the enumeration SX
lock. What do you think about that?

--HPS



Hi,

Another approach which will work is to setup your own USB control 
endpoint xfer, and use that. I'll have a look and see what can be done.


--HPS

___
freebsd-wireless@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
To unsubscribe, send any mail to "freebsd-wireless-unsubscr...@freebsd.org"


Re: Deadlock between device_detach() and usbd_do_request_flags()

2016-09-05 Thread Hans Petter Selasky

On 09/04/16 23:20, Andriy Voskoboinyk wrote:

There is a rare, but reproducible deadlock for wlan(4) drivers:

Thread 1:
 * uhub_explore_handle_re_enumerate() (obtains enum_sx lock)
 * usbd_set_config_index()
 * usb_unconfigure()
 * usb_detach_device()
 * usb_detach_device_sub()
 * 
   typically  is executed here (prevents
another possible deadlock?)
 * ieee80211_ifdetach()
 * ieee80211_vap_destroy()
 * ic_vap_delete>
 * ieee80211_vap_detach()
   here it calls ieee80211_stop() and waits for  -> INIT state
   transition

Thread 2 (started from thread 1):
 * ieee80211_newstate_cb()
 * vap->iv_newstate()
   here: if the driver will try to call usbd_do_request_flags()
   (typically via  / ) it will hang
   (because enum_sx lock is already held by thread 1).


Another way: execute some periodical task that will try to access
some registers (urtwn_temp_calib(), rum_ratectl_task(),
run_ratectl_cb()) while thread 1 is running - deadlock is
here too, since  will wait for them indefinitely
(via ieee80211_draintask())

Right now the most obvious (and, probably, wrong) way is to just
detect & release all locks (usbd_enum_unlock()) for
ieee80211_ifdetach() / ieee80211_draintask() and re-acquire them
later (not tested yet).



Hi,

I think the right solution is to let usbd_do_request_flags() use its own 
SX lock for synchronization, instead of re-using the enumeration SX 
lock. What do you think about that?


--HPS

___
freebsd-wireless@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
To unsubscribe, send any mail to "freebsd-wireless-unsubscr...@freebsd.org"