| 
				
			 | 
			
			
				
				@@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); 
			 | 
		
		
	
		
			
			| 
				33
			 | 
			
				33
			 | 
			
			
				
				 #include <ipxe/netdevice.h> 
			 | 
		
		
	
		
			
			| 
				34
			 | 
			
				34
			 | 
			
			
				
				 #include <ipxe/if_ether.h> 
			 | 
		
		
	
		
			
			| 
				35
			 | 
			
				35
			 | 
			
			
				
				 #include <ipxe/ethernet.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				36
			 | 
			
			
				
				+#include <ipxe/profile.h> 
			 | 
		
		
	
		
			
			| 
				36
			 | 
			
				37
			 | 
			
			
				
				 #include <undi.h> 
			 | 
		
		
	
		
			
			| 
				37
			 | 
			
				38
			 | 
			
			
				
				 #include <undinet.h> 
			 | 
		
		
	
		
			
			| 
				38
			 | 
			
				39
			 | 
			
			
				
				 #include <pxeparent.h> 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -79,6 +80,26 @@ static void undinet_close ( struct net_device *netdev ); 
			 | 
		
		
	
		
			
			| 
				79
			 | 
			
				80
			 | 
			
			
				
				 /** Address of UNDI entry point */ 
			 | 
		
		
	
		
			
			| 
				80
			 | 
			
				81
			 | 
			
			
				
				 static SEGOFF16_t undinet_entry; 
			 | 
		
		
	
		
			
			| 
				81
			 | 
			
				82
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				83
			 | 
			
			
				
				+/** Transmit profiler */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				84
			 | 
			
			
				
				+static struct profiler undinet_tx_profiler __profiler = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				85
			 | 
			
			
				
				+	{ .name = "undinet.tx" }; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				86
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				87
			 | 
			
			
				
				+/** Transmit call profiler */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				88
			 | 
			
			
				
				+static struct profiler undinet_tx_call_profiler __profiler = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				89
			 | 
			
			
				
				+	{ .name = "undinet.tx_call" }; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				90
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				91
			 | 
			
			
				
				+/** IRQ profiler */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				92
			 | 
			
			
				
				+static struct profiler undinet_irq_profiler __profiler = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				93
			 | 
			
			
				
				+	{ .name = "undinet.irq" }; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				94
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				95
			 | 
			
			
				
				+/** ISR call profiler */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				96
			 | 
			
			
				
				+static struct profiler undinet_isr_call_profiler __profiler = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				97
			 | 
			
			
				
				+	{ .name = "undinet.isr_call" }; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				98
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				99
			 | 
			
			
				
				+/** Receive profiler */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				100
			 | 
			
			
				
				+static struct profiler undinet_rx_profiler __profiler = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				101
			 | 
			
			
				
				+	{ .name = "undinet.rx" }; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				102
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				82
			 | 
			
				103
			 | 
			
			
				
				 /***************************************************************************** 
			 | 
		
		
	
		
			
			| 
				83
			 | 
			
				104
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				84
			 | 
			
				105
			 | 
			
			
				
				  * UNDI interrupt service routine 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -194,6 +215,9 @@ static int undinet_transmit ( struct net_device *netdev, 
			 | 
		
		
	
		
			
			| 
				194
			 | 
			
				215
			 | 
			
			
				
				 	size_t len; 
			 | 
		
		
	
		
			
			| 
				195
			 | 
			
				216
			 | 
			
			
				
				 	int rc; 
			 | 
		
		
	
		
			
			| 
				196
			 | 
			
				217
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				218
			 | 
			
			
				
				+	/* Start profiling */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				219
			 | 
			
			
				
				+	profile_start ( &undinet_tx_profiler ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				220
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				197
			 | 
			
				221
			 | 
			
			
				
				 	/* Technically, we ought to make sure that the previous 
			 | 
		
		
	
		
			
			| 
				198
			 | 
			
				222
			 | 
			
			
				
				 	 * transmission has completed before we re-use the buffer. 
			 | 
		
		
	
		
			
			| 
				199
			 | 
			
				223
			 | 
			
			
				
				 	 * However, many PXE stacks (including at least some Intel PXE 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -256,14 +280,16 @@ static int undinet_transmit ( struct net_device *netdev, 
			 | 
		
		
	
		
			
			| 
				256
			 | 
			
				280
			 | 
			
			
				
				 	undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet ); 
			 | 
		
		
	
		
			
			| 
				257
			 | 
			
				281
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				258
			 | 
			
				282
			 | 
			
			
				
				 	/* Issue PXE API call */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				283
			 | 
			
			
				
				+	profile_start ( &undinet_tx_call_profiler ); 
			 | 
		
		
	
		
			
			| 
				259
			 | 
			
				284
			 | 
			
			
				
				 	if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_TRANSMIT, 
			 | 
		
		
	
		
			
			| 
				260
			 | 
			
				285
			 | 
			
			
				
				 				     &undi_transmit, 
			 | 
		
		
	
		
			
			| 
				261
			 | 
			
				286
			 | 
			
			
				
				 				     sizeof ( undi_transmit ) ) ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				262
			 | 
			
				287
			 | 
			
			
				
				 		goto done; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				288
			 | 
			
			
				
				+	profile_stop ( &undinet_tx_call_profiler ); 
			 | 
		
		
	
		
			
			| 
				263
			 | 
			
				289
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				264
			 | 
			
				290
			 | 
			
			
				
				 	/* Free I/O buffer */ 
			 | 
		
		
	
		
			
			| 
				265
			 | 
			
				291
			 | 
			
			
				
				 	netdev_tx_complete ( netdev, iobuf ); 
			 | 
		
		
	
		
			
			| 
				266
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				292
			 | 
			
			
				
				+	profile_stop ( &undinet_tx_profiler ); 
			 | 
		
		
	
		
			
			| 
				267
			 | 
			
				293
			 | 
			
			
				
				  done: 
			 | 
		
		
	
		
			
			| 
				268
			 | 
			
				294
			 | 
			
			
				
				 	return rc; 
			 | 
		
		
	
		
			
			| 
				269
			 | 
			
				295
			 | 
			
			
				
				 } 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -316,10 +342,12 @@ static void undinet_poll ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				316
			 | 
			
				342
			 | 
			
			
				
				 		 */ 
			 | 
		
		
	
		
			
			| 
				317
			 | 
			
				343
			 | 
			
			
				
				 		if ( ! undinet_isr_triggered() ) { 
			 | 
		
		
	
		
			
			| 
				318
			 | 
			
				344
			 | 
			
			
				
				 			/* Allow interrupt to occur */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				345
			 | 
			
			
				
				+			profile_start ( &undinet_irq_profiler ); 
			 | 
		
		
	
		
			
			| 
				319
			 | 
			
				346
			 | 
			
			
				
				 			__asm__ __volatile__ ( REAL_CODE ( "sti\n\t" 
			 | 
		
		
	
		
			
			| 
				320
			 | 
			
				347
			 | 
			
			
				
				 							   "nop\n\t" 
			 | 
		
		
	
		
			
			| 
				321
			 | 
			
				348
			 | 
			
			
				
				 							   "nop\n\t" 
			 | 
		
		
	
		
			
			| 
				322
			 | 
			
				349
			 | 
			
			
				
				 							   "cli\n\t" ) : : ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				350
			 | 
			
			
				
				+			profile_stop ( &undinet_irq_profiler ); 
			 | 
		
		
	
		
			
			| 
				323
			 | 
			
				351
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				324
			 | 
			
				352
			 | 
			
			
				
				 			/* If interrupts are known to be supported, 
			 | 
		
		
	
		
			
			| 
				325
			 | 
			
				353
			 | 
			
			
				
				 			 * then do nothing on this poll; wait for the 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -339,16 +367,19 @@ static void undinet_poll ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				339
			 | 
			
				367
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				340
			 | 
			
				368
			 | 
			
			
				
				 	/* Run through the ISR loop */ 
			 | 
		
		
	
		
			
			| 
				341
			 | 
			
				369
			 | 
			
			
				
				 	while ( 1 ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				370
			 | 
			
			
				
				+		profile_start ( &undinet_isr_call_profiler ); 
			 | 
		
		
	
		
			
			| 
				342
			 | 
			
				371
			 | 
			
			
				
				 		if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR, 
			 | 
		
		
	
		
			
			| 
				343
			 | 
			
				372
			 | 
			
			
				
				 					     &undi_isr, 
			 | 
		
		
	
		
			
			| 
				344
			 | 
			
				373
			 | 
			
			
				
				 					     sizeof ( undi_isr ) ) ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				345
			 | 
			
				374
			 | 
			
			
				
				 			break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				375
			 | 
			
			
				
				+		profile_stop ( &undinet_isr_call_profiler ); 
			 | 
		
		
	
		
			
			| 
				346
			 | 
			
				376
			 | 
			
			
				
				 		switch ( undi_isr.FuncFlag ) { 
			 | 
		
		
	
		
			
			| 
				347
			 | 
			
				377
			 | 
			
			
				
				 		case PXENV_UNDI_ISR_OUT_TRANSMIT: 
			 | 
		
		
	
		
			
			| 
				348
			 | 
			
				378
			 | 
			
			
				
				 			/* We don't care about transmit completions */ 
			 | 
		
		
	
		
			
			| 
				349
			 | 
			
				379
			 | 
			
			
				
				 			break; 
			 | 
		
		
	
		
			
			| 
				350
			 | 
			
				380
			 | 
			
			
				
				 		case PXENV_UNDI_ISR_OUT_RECEIVE: 
			 | 
		
		
	
		
			
			| 
				351
			 | 
			
				381
			 | 
			
			
				
				 			/* Packet fragment received */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				382
			 | 
			
			
				
				+			profile_start ( &undinet_rx_profiler ); 
			 | 
		
		
	
		
			
			| 
				352
			 | 
			
				383
			 | 
			
			
				
				 			len = undi_isr.FrameLength; 
			 | 
		
		
	
		
			
			| 
				353
			 | 
			
				384
			 | 
			
			
				
				 			frag_len = undi_isr.BufferLength; 
			 | 
		
		
	
		
			
			| 
				354
			 | 
			
				385
			 | 
			
			
				
				 			reserve_len = ( -undi_isr.FrameHeaderLength & 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -393,6 +424,7 @@ static void undinet_poll ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				393
			 | 
			
				424
			 | 
			
			
				
				 				if ( undinic->hacks & UNDI_HACK_EB54 ) 
			 | 
		
		
	
		
			
			| 
				394
			 | 
			
				425
			 | 
			
			
				
				 					--last_trigger_count; 
			 | 
		
		
	
		
			
			| 
				395
			 | 
			
				426
			 | 
			
			
				
				 			} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				427
			 | 
			
			
				
				+			profile_stop ( &undinet_rx_profiler ); 
			 | 
		
		
	
		
			
			| 
				396
			 | 
			
				428
			 | 
			
			
				
				 			break; 
			 | 
		
		
	
		
			
			| 
				397
			 | 
			
				429
			 | 
			
			
				
				 		case PXENV_UNDI_ISR_OUT_DONE: 
			 | 
		
		
	
		
			
			| 
				398
			 | 
			
				430
			 | 
			
			
				
				 			/* Processing complete */ 
			 |