|  | @@ -38,6 +38,17 @@
 | 
		
	
		
			
			| 38 | 38 |  #include <gpxe/shutdown.h>
 | 
		
	
		
			
			| 39 | 39 |  #include "pxe.h"
 | 
		
	
		
			
			| 40 | 40 |  
 | 
		
	
		
			
			|  | 41 | +/**
 | 
		
	
		
			
			|  | 42 | + * Count of outstanding transmitted packets
 | 
		
	
		
			
			|  | 43 | + *
 | 
		
	
		
			
			|  | 44 | + * This is incremented each time PXENV_UNDI_TRANSMIT is called, and
 | 
		
	
		
			
			|  | 45 | + * decremented each time that PXENV_UNDI_ISR is called with the TX
 | 
		
	
		
			
			|  | 46 | + * queue empty, stopping when the count reaches zero.  This allows us
 | 
		
	
		
			
			|  | 47 | + * to provide a pessimistic approximation of TX completion events to
 | 
		
	
		
			
			|  | 48 | + * the PXE NBP simply by monitoring the netdev's TX queue.
 | 
		
	
		
			
			|  | 49 | + */
 | 
		
	
		
			
			|  | 50 | +static int undi_tx_count = 0;
 | 
		
	
		
			
			|  | 51 | +
 | 
		
	
		
			
			| 41 | 52 |  /* PXENV_UNDI_STARTUP
 | 
		
	
		
			
			| 42 | 53 |   *
 | 
		
	
		
			
			| 43 | 54 |   * Status: working
 | 
		
	
	
		
			
			|  | @@ -56,6 +67,8 @@ PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
 | 
		
	
		
			
			| 56 | 67 |  PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
 | 
		
	
		
			
			| 57 | 68 |  	DBG ( "PXENV_UNDI_CLEANUP" );
 | 
		
	
		
			
			| 58 | 69 |  
 | 
		
	
		
			
			|  | 70 | +	netdev_close ( pxe_netdev );
 | 
		
	
		
			
			|  | 71 | +
 | 
		
	
		
			
			| 59 | 72 |  	undi_cleanup->Status = PXENV_STATUS_SUCCESS;
 | 
		
	
		
			
			| 60 | 73 |  	return PXENV_EXIT_SUCCESS;
 | 
		
	
		
			
			| 61 | 74 |  }
 | 
		
	
	
		
			
			|  | @@ -78,8 +91,17 @@ PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE
 | 
		
	
		
			
			| 78 | 91 |   */
 | 
		
	
		
			
			| 79 | 92 |  PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET
 | 
		
	
		
			
			| 80 | 93 |  					*undi_reset_adapter ) {
 | 
		
	
		
			
			|  | 94 | +	int rc;
 | 
		
	
		
			
			|  | 95 | +
 | 
		
	
		
			
			| 81 | 96 |  	DBG ( "PXENV_UNDI_RESET_ADAPTER" );
 | 
		
	
		
			
			| 82 | 97 |  
 | 
		
	
		
			
			|  | 98 | +	netdev_close ( pxe_netdev );
 | 
		
	
		
			
			|  | 99 | +	undi_tx_count = 0;
 | 
		
	
		
			
			|  | 100 | +	if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 ) {
 | 
		
	
		
			
			|  | 101 | +		undi_reset_adapter->Status = PXENV_STATUS ( rc );
 | 
		
	
		
			
			|  | 102 | +		return PXENV_EXIT_FAILURE;
 | 
		
	
		
			
			|  | 103 | +	}
 | 
		
	
		
			
			|  | 104 | +
 | 
		
	
		
			
			| 83 | 105 |  	undi_reset_adapter->Status = PXENV_STATUS_SUCCESS;
 | 
		
	
		
			
			| 84 | 106 |  	return PXENV_EXIT_SUCCESS;
 | 
		
	
		
			
			| 85 | 107 |  }
 | 
		
	
	
		
			
			|  | @@ -103,15 +125,14 @@ PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN
 | 
		
	
		
			
			| 103 | 125 |   * Status: working
 | 
		
	
		
			
			| 104 | 126 |   */
 | 
		
	
		
			
			| 105 | 127 |  PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
 | 
		
	
		
			
			|  | 128 | +	int rc;
 | 
		
	
		
			
			|  | 129 | +
 | 
		
	
		
			
			| 106 | 130 |  	DBG ( "PXENV_UNDI_OPEN" );
 | 
		
	
		
			
			| 107 | 131 |  
 | 
		
	
		
			
			| 108 |  | -#if 0
 | 
		
	
		
			
			| 109 |  | -	/* PXESPEC: This is where we choose to enable interrupts.
 | 
		
	
		
			
			| 110 |  | -	 * Can't actually find where we're meant to in the PXE spec,
 | 
		
	
		
			
			| 111 |  | -	 * but this should work.
 | 
		
	
		
			
			| 112 |  | -	 */
 | 
		
	
		
			
			| 113 |  | -	eth_irq ( ENABLE );
 | 
		
	
		
			
			| 114 |  | -#endif
 | 
		
	
		
			
			|  | 132 | +	if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 ) {
 | 
		
	
		
			
			|  | 133 | +		undi_open->Status = PXENV_STATUS ( rc );
 | 
		
	
		
			
			|  | 134 | +		return PXENV_EXIT_FAILURE;
 | 
		
	
		
			
			|  | 135 | +	}
 | 
		
	
		
			
			| 115 | 136 |  
 | 
		
	
		
			
			| 116 | 137 |  	undi_open->Status = PXENV_STATUS_SUCCESS;
 | 
		
	
		
			
			| 117 | 138 |  	return PXENV_EXIT_SUCCESS;
 | 
		
	
	
		
			
			|  | @@ -124,6 +145,9 @@ PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
 | 
		
	
		
			
			| 124 | 145 |  PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
 | 
		
	
		
			
			| 125 | 146 |  	DBG ( "PXENV_UNDI_CLOSE" );
 | 
		
	
		
			
			| 126 | 147 |  
 | 
		
	
		
			
			|  | 148 | +	netdev_close ( pxe_netdev );
 | 
		
	
		
			
			|  | 149 | +	undi_tx_count = 0;
 | 
		
	
		
			
			|  | 150 | +
 | 
		
	
		
			
			| 127 | 151 |  	undi_close->Status = PXENV_STATUS_SUCCESS;
 | 
		
	
		
			
			| 128 | 152 |  	return PXENV_EXIT_SUCCESS;
 | 
		
	
		
			
			| 129 | 153 |  }
 | 
		
	
	
		
			
			|  | @@ -200,7 +224,8 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
 | 
		
	
		
			
			| 200 | 224 |  		rc = net_tx ( iobuf, pxe_netdev, net_protocol, ll_dest );
 | 
		
	
		
			
			| 201 | 225 |  	}
 | 
		
	
		
			
			| 202 | 226 |  
 | 
		
	
		
			
			| 203 |  | -#warning "TX completion?"
 | 
		
	
		
			
			|  | 227 | +	/* Flag transmission as in-progress */
 | 
		
	
		
			
			|  | 228 | +	undi_tx_count++;
 | 
		
	
		
			
			| 204 | 229 |  
 | 
		
	
		
			
			| 205 | 230 |  	undi_transmit->Status = PXENV_STATUS ( rc );
 | 
		
	
		
			
			| 206 | 231 |  	return ( ( rc == 0 ) ? PXENV_EXIT_SUCCESS : PXENV_EXIT_FAILURE );
 | 
		
	
	
		
			
			|  | @@ -490,7 +515,16 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
 | 
		
	
		
			
			| 490 | 515 |  	case PXENV_UNDI_ISR_IN_PROCESS :
 | 
		
	
		
			
			| 491 | 516 |  	case PXENV_UNDI_ISR_IN_GET_NEXT :
 | 
		
	
		
			
			| 492 | 517 |  		DBG ( " PROCESS/GET_NEXT" );
 | 
		
	
		
			
			| 493 |  | -		
 | 
		
	
		
			
			|  | 518 | +
 | 
		
	
		
			
			|  | 519 | +		/* If we have not yet marked a TX as complete, and the
 | 
		
	
		
			
			|  | 520 | +		 * netdev TX queue is empty, report the TX completion.
 | 
		
	
		
			
			|  | 521 | +		 */
 | 
		
	
		
			
			|  | 522 | +		if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) {
 | 
		
	
		
			
			|  | 523 | +			undi_tx_count--;
 | 
		
	
		
			
			|  | 524 | +			undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT;
 | 
		
	
		
			
			|  | 525 | +			break;
 | 
		
	
		
			
			|  | 526 | +		}
 | 
		
	
		
			
			|  | 527 | +
 | 
		
	
		
			
			| 494 | 528 |  		/* Remove first packet from netdev RX queue */
 | 
		
	
		
			
			| 495 | 529 |  		iobuf = netdev_rx_dequeue ( pxe_netdev );
 | 
		
	
		
			
			| 496 | 530 |  		if ( ! iobuf ) {
 |