|
@@ -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
|
|