|  | @@ -19,6 +19,7 @@
 | 
		
	
		
			
			| 19 | 19 |  FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 20 | 20 |  
 | 
		
	
		
			
			| 21 | 21 |  #include <string.h>
 | 
		
	
		
			
			|  | 22 | +#include <unistd.h>
 | 
		
	
		
			
			| 22 | 23 |  #include <pxe.h>
 | 
		
	
		
			
			| 23 | 24 |  #include <realmode.h>
 | 
		
	
		
			
			| 24 | 25 |  #include <pic8259.h>
 | 
		
	
	
		
			
			|  | @@ -34,7 +35,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 34 | 35 |  #include <undinet.h>
 | 
		
	
		
			
			| 35 | 36 |  #include <pxeparent.h>
 | 
		
	
		
			
			| 36 | 37 |  
 | 
		
	
		
			
			| 37 |  | -
 | 
		
	
		
			
			| 38 | 38 |  /** @file
 | 
		
	
		
			
			| 39 | 39 |   *
 | 
		
	
		
			
			| 40 | 40 |   * UNDI network device driver
 | 
		
	
	
		
			
			|  | @@ -63,6 +63,12 @@ struct undi_nic {
 | 
		
	
		
			
			| 63 | 63 |  
 | 
		
	
		
			
			| 64 | 64 |  /** @} */
 | 
		
	
		
			
			| 65 | 65 |  
 | 
		
	
		
			
			|  | 66 | +/** Maximum number of times to retry PXENV_UNDI_INITIALIZE */
 | 
		
	
		
			
			|  | 67 | +#define UNDI_INITIALIZE_RETRY_MAX 10
 | 
		
	
		
			
			|  | 68 | +
 | 
		
	
		
			
			|  | 69 | +/** Delay between retries of PXENV_UNDI_INITIALIZE */
 | 
		
	
		
			
			|  | 70 | +#define UNDI_INITIALIZE_RETRY_DELAY_MS 200
 | 
		
	
		
			
			|  | 71 | +
 | 
		
	
		
			
			| 66 | 72 |  static void undinet_close ( struct net_device *netdev );
 | 
		
	
		
			
			| 67 | 73 |  
 | 
		
	
		
			
			| 68 | 74 |  /** Address of UNDI entry point */
 | 
		
	
	
		
			
			|  | @@ -482,12 +488,13 @@ int undinet_probe ( struct undi_device *undi ) {
 | 
		
	
		
			
			| 482 | 488 |  	struct undi_nic *undinic;
 | 
		
	
		
			
			| 483 | 489 |  	struct s_PXENV_START_UNDI start_undi;
 | 
		
	
		
			
			| 484 | 490 |  	struct s_PXENV_UNDI_STARTUP undi_startup;
 | 
		
	
		
			
			| 485 |  | -	struct s_PXENV_UNDI_INITIALIZE undi_initialize;
 | 
		
	
		
			
			|  | 491 | +	struct s_PXENV_UNDI_INITIALIZE undi_init;
 | 
		
	
		
			
			| 486 | 492 |  	struct s_PXENV_UNDI_GET_INFORMATION undi_info;
 | 
		
	
		
			
			| 487 | 493 |  	struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
 | 
		
	
		
			
			| 488 | 494 |  	struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
 | 
		
	
		
			
			| 489 | 495 |  	struct s_PXENV_UNDI_CLEANUP undi_cleanup;
 | 
		
	
		
			
			| 490 | 496 |  	struct s_PXENV_STOP_UNDI stop_undi;
 | 
		
	
		
			
			|  | 497 | +	unsigned int retry;
 | 
		
	
		
			
			| 491 | 498 |  	int rc;
 | 
		
	
		
			
			| 492 | 499 |  
 | 
		
	
		
			
			| 493 | 500 |  	/* Allocate net device */
 | 
		
	
	
		
			
			|  | @@ -524,12 +531,27 @@ int undinet_probe ( struct undi_device *undi ) {
 | 
		
	
		
			
			| 524 | 531 |  					     &undi_startup,
 | 
		
	
		
			
			| 525 | 532 |  					     sizeof ( undi_startup ) ) ) != 0 )
 | 
		
	
		
			
			| 526 | 533 |  			goto err_undi_startup;
 | 
		
	
		
			
			| 527 |  | -		memset ( &undi_initialize, 0, sizeof ( undi_initialize ) );
 | 
		
	
		
			
			| 528 |  | -		if ( ( rc = pxeparent_call ( undinet_entry,
 | 
		
	
		
			
			| 529 |  | -					     PXENV_UNDI_INITIALIZE,
 | 
		
	
		
			
			| 530 |  | -					     &undi_initialize,
 | 
		
	
		
			
			| 531 |  | -					     sizeof ( undi_initialize ))) != 0 )
 | 
		
	
		
			
			| 532 |  | -			goto err_undi_initialize;
 | 
		
	
		
			
			|  | 534 | +		/* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
 | 
		
	
		
			
			|  | 535 | +		 * due to a transient condition (e.g. media test
 | 
		
	
		
			
			|  | 536 | +		 * failing because the link has only just come out of
 | 
		
	
		
			
			|  | 537 | +		 * reset).  We may therefore need to retry this call
 | 
		
	
		
			
			|  | 538 | +		 * several times.
 | 
		
	
		
			
			|  | 539 | +		 */
 | 
		
	
		
			
			|  | 540 | +		for ( retry = 0 ; ; ) {
 | 
		
	
		
			
			|  | 541 | +			memset ( &undi_init, 0, sizeof ( undi_init ) );
 | 
		
	
		
			
			|  | 542 | +			if ( ( rc = pxeparent_call ( undinet_entry,
 | 
		
	
		
			
			|  | 543 | +						     PXENV_UNDI_INITIALIZE,
 | 
		
	
		
			
			|  | 544 | +						     &undi_init,
 | 
		
	
		
			
			|  | 545 | +						     sizeof ( undi_init ))) ==0)
 | 
		
	
		
			
			|  | 546 | +				break;
 | 
		
	
		
			
			|  | 547 | +			if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
 | 
		
	
		
			
			|  | 548 | +				goto err_undi_initialize;
 | 
		
	
		
			
			|  | 549 | +			DBGC ( undinic, "UNDINIC %p retrying "
 | 
		
	
		
			
			|  | 550 | +			       "PXENV_UNDI_INITIALIZE (retry %d)\n",
 | 
		
	
		
			
			|  | 551 | +			       undinic, retry );
 | 
		
	
		
			
			|  | 552 | +			/* Delay to allow link to settle if necessary */
 | 
		
	
		
			
			|  | 553 | +			mdelay ( UNDI_INITIALIZE_RETRY_DELAY_MS );
 | 
		
	
		
			
			|  | 554 | +		}
 | 
		
	
		
			
			| 533 | 555 |  	}
 | 
		
	
		
			
			| 534 | 556 |  	undi->flags |= UNDI_FL_INITIALIZED;
 | 
		
	
		
			
			| 535 | 557 |  
 |