Browse Source

[e1000] Implement zero-copy receive

Co-Authored by: Marty Connor <mdc@etherboot.org>
Signed-off-by: Marty Connor <mdc@etherboot.org>
tags/v1.0.0-rc1
Thomas Miletich 15 years ago
parent
commit
2a9688b880
1 changed files with 83 additions and 63 deletions
  1. 83
    63
      src/drivers/net/e1000/e1000.c

+ 83
- 63
src/drivers/net/e1000/e1000.c View File

290
         E1000_WRITE_FLUSH ( hw );
290
         E1000_WRITE_FLUSH ( hw );
291
 }
291
 }
292
 
292
 
293
+static void
294
+e1000_free_rx_resources ( struct e1000_adapter *adapter )
295
+{
296
+	int i;
297
+
298
+	DBG ( "e1000_free_rx_resources\n" );
299
+
300
+	free_dma ( adapter->rx_base, adapter->rx_ring_size );
301
+
302
+	for ( i = 0; i < NUM_RX_DESC; i++ ) {
303
+		free_iob ( adapter->rx_iobuf[i] );
304
+	}
305
+}
306
+
307
+/**
308
+ * e1000_refill_rx_ring - allocate Rx io_buffers
309
+ *
310
+ * @v adapter	e1000 private structure
311
+ *
312
+ * @ret rc       Returns 0 on success, negative on failure
313
+ **/
314
+int e1000_refill_rx_ring ( struct e1000_adapter *adapter )
315
+{
316
+	int i, rx_curr;
317
+	int rc = 0;
318
+	struct e1000_rx_desc *rx_curr_desc;
319
+	struct e1000_hw *hw = &adapter->hw;
320
+	struct io_buffer *iob;
321
+
322
+	DBG ("e1000_refill_rx_ring\n");
323
+
324
+	for ( i = 0; i < NUM_RX_DESC; i++ ) {
325
+		rx_curr = ( ( adapter->rx_curr + i ) % NUM_RX_DESC );
326
+		rx_curr_desc = adapter->rx_base + rx_curr;
327
+
328
+		if ( rx_curr_desc->status & E1000_RXD_STAT_DD )
329
+			continue;
330
+
331
+		if ( adapter->rx_iobuf[rx_curr] != NULL )
332
+			continue;
333
+
334
+		DBG2 ( "Refilling rx desc %d\n", rx_curr );
335
+
336
+		iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
337
+		adapter->rx_iobuf[rx_curr] = iob;
338
+
339
+		if ( ! iob ) {
340
+			DBG ( "alloc_iob failed\n" );
341
+			rc = -ENOMEM;
342
+			break;
343
+		} else {
344
+			rx_curr_desc->buffer_addr = virt_to_bus ( iob->data );
345
+
346
+			E1000_WRITE_REG ( hw, RDT, rx_curr );
347
+		}
348
+	}
349
+	return rc;
350
+}
351
+
293
 /**
352
 /**
294
  * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
353
  * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
295
  *
354
  *
300
 static int
359
 static int
301
 e1000_setup_rx_resources ( struct e1000_adapter *adapter )
360
 e1000_setup_rx_resources ( struct e1000_adapter *adapter )
302
 {
361
 {
303
-	int i, j;
304
-	struct e1000_rx_desc *rx_curr_desc;
362
+	int i, rc = 0;
305
 	
363
 	
306
 	DBG ( "e1000_setup_rx_resources\n" );
364
 	DBG ( "e1000_setup_rx_resources\n" );
307
 	
365
 	
311
 
369
 
312
         adapter->rx_base = 
370
         adapter->rx_base = 
313
         	malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
371
         	malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
314
-        		     
372
+
315
        	if ( ! adapter->rx_base ) {
373
        	if ( ! adapter->rx_base ) {
316
        		return -ENOMEM;
374
        		return -ENOMEM;
317
 	}
375
 	}
318
 	memset ( adapter->rx_base, 0, adapter->rx_ring_size );
376
 	memset ( adapter->rx_base, 0, adapter->rx_ring_size );
319
 
377
 
320
 	for ( i = 0; i < NUM_RX_DESC; i++ ) {
378
 	for ( i = 0; i < NUM_RX_DESC; i++ ) {
321
-	
322
-		adapter->rx_iobuf[i] = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
323
-		
324
-		/* If unable to allocate all iobufs, free any that
325
-		 * were successfully allocated, and return an error 
326
-		 */
327
-		if ( ! adapter->rx_iobuf[i] ) {
328
-			for ( j = 0; j < i; j++ ) {
329
-				free_iob ( adapter->rx_iobuf[j] );
330
-			}
331
-			return -ENOMEM;
332
-		}
333
-
334
-		rx_curr_desc = ( void * ) ( adapter->rx_base ) + 
335
-					  ( i * sizeof ( *adapter->rx_base ) ); 
336
-			
337
-		rx_curr_desc->buffer_addr = virt_to_bus ( adapter->rx_iobuf[i]->data );	
338
-
339
-		DBG ( "i = %d  rx_curr_desc->buffer_addr = %#16llx\n", 
340
-		      i, rx_curr_desc->buffer_addr );
341
-		
342
-	}	
343
-	return 0;
344
-}
345
-
346
-static void
347
-e1000_free_rx_resources ( struct e1000_adapter *adapter )
348
-{
349
-	int i;
350
-	
351
-	DBG ( "e1000_free_rx_resources\n" );
379
+		/* let e1000_refill_rx_ring() io_buffer allocations */
380
+		adapter->rx_iobuf[i] = NULL;
381
+	}
352
 
382
 
353
-        free_dma ( adapter->rx_base, adapter->rx_ring_size );
383
+	/* allocate io_buffers */
384
+	rc = e1000_refill_rx_ring ( adapter );
385
+	if ( rc < 0 )
386
+		e1000_free_rx_resources ( adapter );
354
 
387
 
355
-	for ( i = 0; i < NUM_RX_DESC; i++ ) {
356
-		free_iob ( adapter->rx_iobuf[i] );
357
-	}
388
+	return rc;
358
 }
389
 }
359
 
390
 
360
 /**
391
 /**
676
 	uint32_t rx_status;
707
 	uint32_t rx_status;
677
 	uint32_t rx_len;
708
 	uint32_t rx_len;
678
 	uint32_t rx_err;
709
 	uint32_t rx_err;
679
-	struct io_buffer *rx_iob;
680
 	struct e1000_tx_desc *tx_curr_desc;
710
 	struct e1000_tx_desc *tx_curr_desc;
681
 	struct e1000_rx_desc *rx_curr_desc;
711
 	struct e1000_rx_desc *rx_curr_desc;
682
 	uint32_t i;
712
 	uint32_t i;
683
-	uint64_t tmp_buffer_addr;
684
-	
713
+
685
 	DBGP ( "e1000_poll\n" );
714
 	DBGP ( "e1000_poll\n" );
686
 
715
 
687
 	/* Acknowledge interrupts */
716
 	/* Acknowledge interrupts */
741
 		if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
770
 		if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
742
 			break;
771
 			break;
743
 
772
 
773
+		if ( adapter->rx_iobuf[i] == NULL )
774
+			break;
775
+
744
 		DBG ( "RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, RCTL ) );
776
 		DBG ( "RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, RCTL ) );
745
 	
777
 	
746
 		rx_len = rx_curr_desc->length;
778
 		rx_len = rx_curr_desc->length;
747
 
779
 
748
                 DBG ( "Received packet, rx_curr: %d  rx_status: %#08x  rx_len: %d\n",
780
                 DBG ( "Received packet, rx_curr: %d  rx_status: %#08x  rx_len: %d\n",
749
                       i, rx_status, rx_len );
781
                       i, rx_status, rx_len );
750
-                
782
+
751
                 rx_err = rx_curr_desc->errors;
783
                 rx_err = rx_curr_desc->errors;
752
-                
784
+
785
+		iob_put ( adapter->rx_iobuf[i], rx_len );
786
+
753
 		if ( rx_err & E1000_RXD_ERR_FRAME_ERR_MASK ) {
787
 		if ( rx_err & E1000_RXD_ERR_FRAME_ERR_MASK ) {
754
 		
788
 		
755
-			netdev_rx_err ( netdev, NULL, -EINVAL );
789
+			netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL );
756
 			DBG ( "e1000_poll: Corrupted packet received!"
790
 			DBG ( "e1000_poll: Corrupted packet received!"
757
 			      " rx_err: %#08x\n", rx_err );
791
 			      " rx_err: %#08x\n", rx_err );
758
 		} else 	{
792
 		} else 	{
759
-		
760
-			/* If unable allocate space for this packet,
761
-			 *  try again next poll
762
-			 */
763
-			rx_iob = alloc_iob ( rx_len );
764
-			if ( ! rx_iob ) 
765
-				break;
766
-				
767
-			memcpy ( iob_put ( rx_iob, rx_len ), 
768
-				adapter->rx_iobuf[i]->data, rx_len );
769
-				
770
-			/* Add this packet to the receive queue. 
771
-			 */
772
-			netdev_rx ( netdev, rx_iob );
793
+			/* Add this packet to the receive queue. */
794
+			netdev_rx ( netdev, adapter->rx_iobuf[i] );
773
 		}
795
 		}
796
+		adapter->rx_iobuf[i] = NULL;
774
 
797
 
775
-		tmp_buffer_addr = rx_curr_desc->buffer_addr;
776
 		memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );
798
 		memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );
777
-		rx_curr_desc->buffer_addr = tmp_buffer_addr;
778
-
779
-		E1000_WRITE_REG ( hw, RDT, adapter->rx_curr );
780
 
799
 
781
 		adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC;
800
 		adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC;
782
 	}
801
 	}
783
-}				
802
+	e1000_refill_rx_ring(adapter);
803
+}
784
 
804
 
785
 /**
805
 /**
786
  * e1000_irq - enable or Disable interrupts
806
  * e1000_irq - enable or Disable interrupts

Loading…
Cancel
Save