Browse Source

Add mechanism for providing TX completion events.

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
8f37a6a424
1 changed files with 43 additions and 9 deletions
  1. 43
    9
      src/interface/pxe/pxe_undi.c

+ 43
- 9
src/interface/pxe/pxe_undi.c View File

38
 #include <gpxe/shutdown.h>
38
 #include <gpxe/shutdown.h>
39
 #include "pxe.h"
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
 /* PXENV_UNDI_STARTUP
52
 /* PXENV_UNDI_STARTUP
42
  *
53
  *
43
  * Status: working
54
  * Status: working
56
 PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
67
 PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
57
 	DBG ( "PXENV_UNDI_CLEANUP" );
68
 	DBG ( "PXENV_UNDI_CLEANUP" );
58
 
69
 
70
+	netdev_close ( pxe_netdev );
71
+
59
 	undi_cleanup->Status = PXENV_STATUS_SUCCESS;
72
 	undi_cleanup->Status = PXENV_STATUS_SUCCESS;
60
 	return PXENV_EXIT_SUCCESS;
73
 	return PXENV_EXIT_SUCCESS;
61
 }
74
 }
78
  */
91
  */
79
 PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET
92
 PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET
80
 					*undi_reset_adapter ) {
93
 					*undi_reset_adapter ) {
94
+	int rc;
95
+
81
 	DBG ( "PXENV_UNDI_RESET_ADAPTER" );
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
 	undi_reset_adapter->Status = PXENV_STATUS_SUCCESS;
105
 	undi_reset_adapter->Status = PXENV_STATUS_SUCCESS;
84
 	return PXENV_EXIT_SUCCESS;
106
 	return PXENV_EXIT_SUCCESS;
85
 }
107
 }
103
  * Status: working
125
  * Status: working
104
  */
126
  */
105
 PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
127
 PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
128
+	int rc;
129
+
106
 	DBG ( "PXENV_UNDI_OPEN" );
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
 	undi_open->Status = PXENV_STATUS_SUCCESS;
137
 	undi_open->Status = PXENV_STATUS_SUCCESS;
117
 	return PXENV_EXIT_SUCCESS;
138
 	return PXENV_EXIT_SUCCESS;
124
 PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
145
 PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
125
 	DBG ( "PXENV_UNDI_CLOSE" );
146
 	DBG ( "PXENV_UNDI_CLOSE" );
126
 
147
 
148
+	netdev_close ( pxe_netdev );
149
+	undi_tx_count = 0;
150
+
127
 	undi_close->Status = PXENV_STATUS_SUCCESS;
151
 	undi_close->Status = PXENV_STATUS_SUCCESS;
128
 	return PXENV_EXIT_SUCCESS;
152
 	return PXENV_EXIT_SUCCESS;
129
 }
153
 }
200
 		rc = net_tx ( iobuf, pxe_netdev, net_protocol, ll_dest );
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
 	undi_transmit->Status = PXENV_STATUS ( rc );
230
 	undi_transmit->Status = PXENV_STATUS ( rc );
206
 	return ( ( rc == 0 ) ? PXENV_EXIT_SUCCESS : PXENV_EXIT_FAILURE );
231
 	return ( ( rc == 0 ) ? PXENV_EXIT_SUCCESS : PXENV_EXIT_FAILURE );
490
 	case PXENV_UNDI_ISR_IN_PROCESS :
515
 	case PXENV_UNDI_ISR_IN_PROCESS :
491
 	case PXENV_UNDI_ISR_IN_GET_NEXT :
516
 	case PXENV_UNDI_ISR_IN_GET_NEXT :
492
 		DBG ( " PROCESS/GET_NEXT" );
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
 		/* Remove first packet from netdev RX queue */
528
 		/* Remove first packet from netdev RX queue */
495
 		iobuf = netdev_rx_dequeue ( pxe_netdev );
529
 		iobuf = netdev_rx_dequeue ( pxe_netdev );
496
 		if ( ! iobuf ) {
530
 		if ( ! iobuf ) {

Loading…
Cancel
Save