|  | @@ -76,11 +76,36 @@ static void efi_udelay ( unsigned long usecs ) {
 | 
		
	
		
			
			| 76 | 76 |   * @ret ticks		Current time, in ticks
 | 
		
	
		
			
			| 77 | 77 |   */
 | 
		
	
		
			
			| 78 | 78 |  static unsigned long efi_currticks ( void ) {
 | 
		
	
		
			
			|  | 79 | +	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			| 79 | 80 |  
 | 
		
	
		
			
			| 80 |  | -	/* EFI provides no clean way for device drivers to shut down
 | 
		
	
		
			
			| 81 |  | -	 * in preparation for handover to a booted operating system.
 | 
		
	
		
			
			| 82 |  | -	 * The platform firmware simply doesn't bother to call the
 | 
		
	
		
			
			| 83 |  | -	 * drivers' Stop() methods.  Instead, drivers must register an
 | 
		
	
		
			
			|  | 81 | +	/* UEFI manages to ingeniously combine the worst aspects of
 | 
		
	
		
			
			|  | 82 | +	 * both polling and interrupt-driven designs.  There is no way
 | 
		
	
		
			
			|  | 83 | +	 * to support proper interrupt-driven operation, since there
 | 
		
	
		
			
			|  | 84 | +	 * is no way to hook in an interrupt service routine.  A
 | 
		
	
		
			
			|  | 85 | +	 * mockery of interrupts is provided by UEFI timers, which
 | 
		
	
		
			
			|  | 86 | +	 * trigger at a preset rate and can fire at any time.
 | 
		
	
		
			
			|  | 87 | +	 *
 | 
		
	
		
			
			|  | 88 | +	 * We therefore have all of the downsides of a polling design
 | 
		
	
		
			
			|  | 89 | +	 * (inefficiency and inability to sleep until something
 | 
		
	
		
			
			|  | 90 | +	 * interesting happens) combined with all of the downsides of
 | 
		
	
		
			
			|  | 91 | +	 * an interrupt-driven design (the complexity of code that
 | 
		
	
		
			
			|  | 92 | +	 * could be preempted at any time).
 | 
		
	
		
			
			|  | 93 | +	 *
 | 
		
	
		
			
			|  | 94 | +	 * The UEFI specification expects us to litter the entire
 | 
		
	
		
			
			|  | 95 | +	 * codebase with calls to RaiseTPL() as needed for sections of
 | 
		
	
		
			
			|  | 96 | +	 * code that are not reentrant.  Since this doesn't actually
 | 
		
	
		
			
			|  | 97 | +	 * gain us any substantive benefits (since even with such
 | 
		
	
		
			
			|  | 98 | +	 * calls we would still be suffering from the limitations of a
 | 
		
	
		
			
			|  | 99 | +	 * polling design), we instead choose to run at TPL_CALLBACK
 | 
		
	
		
			
			|  | 100 | +	 * almost all of the time, dropping to TPL_APPLICATION to
 | 
		
	
		
			
			|  | 101 | +	 * allow timer ticks to occur.
 | 
		
	
		
			
			|  | 102 | +	 *
 | 
		
	
		
			
			|  | 103 | +	 *
 | 
		
	
		
			
			|  | 104 | +	 * For added excitement, UEFI provides no clean way for device
 | 
		
	
		
			
			|  | 105 | +	 * drivers to shut down in preparation for handover to a
 | 
		
	
		
			
			|  | 106 | +	 * booted operating system.  The platform firmware simply
 | 
		
	
		
			
			|  | 107 | +	 * doesn't bother to call the drivers' Stop() methods.
 | 
		
	
		
			
			|  | 108 | +	 * Instead, all non-trivial drivers must register an
 | 
		
	
		
			
			| 84 | 109 |  	 * EVT_SIGNAL_EXIT_BOOT_SERVICES event to be signalled when
 | 
		
	
		
			
			| 85 | 110 |  	 * ExitBootServices() is called, and clean up without any
 | 
		
	
		
			
			| 86 | 111 |  	 * reference to the EFI driver model.
 | 
		
	
	
		
			
			|  | @@ -97,10 +122,14 @@ static unsigned long efi_currticks ( void ) {
 | 
		
	
		
			
			| 97 | 122 |  	 * the API lazily assumes that the host system continues to
 | 
		
	
		
			
			| 98 | 123 |  	 * travel through time in the usual direction.  Work around
 | 
		
	
		
			
			| 99 | 124 |  	 * EFI's violation of this assumption by falling back to a
 | 
		
	
		
			
			| 100 |  | -	 * simple free-running monotonic counter.
 | 
		
	
		
			
			|  | 125 | +	 * simple free-running monotonic counter during shutdown.
 | 
		
	
		
			
			| 101 | 126 |  	 */
 | 
		
	
		
			
			| 102 |  | -	if ( efi_shutdown_in_progress )
 | 
		
	
		
			
			|  | 127 | +	if ( efi_shutdown_in_progress ) {
 | 
		
	
		
			
			| 103 | 128 |  		efi_jiffies++;
 | 
		
	
		
			
			|  | 129 | +	} else {
 | 
		
	
		
			
			|  | 130 | +		bs->RestoreTPL ( TPL_APPLICATION );
 | 
		
	
		
			
			|  | 131 | +		bs->RaiseTPL ( TPL_CALLBACK );
 | 
		
	
		
			
			|  | 132 | +	}
 | 
		
	
		
			
			| 104 | 133 |  
 | 
		
	
		
			
			| 105 | 134 |  	return ( efi_jiffies * ( TICKS_PER_SEC / EFI_JIFFIES_PER_SEC ) );
 | 
		
	
		
			
			| 106 | 135 |  }
 |