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 14 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,6 +290,65 @@ e1000_configure_tx ( struct e1000_adapter *adapter )
290 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 353
  * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
295 354
  *
@@ -300,8 +359,7 @@ e1000_configure_tx ( struct e1000_adapter *adapter )
300 359
 static int
301 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 364
 	DBG ( "e1000_setup_rx_resources\n" );
307 365
 	
@@ -311,50 +369,23 @@ e1000_setup_rx_resources ( struct e1000_adapter *adapter )
311 369
 
312 370
         adapter->rx_base = 
313 371
         	malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
314
-        		     
372
+
315 373
        	if ( ! adapter->rx_base ) {
316 374
        		return -ENOMEM;
317 375
 	}
318 376
 	memset ( adapter->rx_base, 0, adapter->rx_ring_size );
319 377
 
320 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,12 +707,10 @@ e1000_poll ( struct net_device *netdev )
676 707
 	uint32_t rx_status;
677 708
 	uint32_t rx_len;
678 709
 	uint32_t rx_err;
679
-	struct io_buffer *rx_iob;
680 710
 	struct e1000_tx_desc *tx_curr_desc;
681 711
 	struct e1000_rx_desc *rx_curr_desc;
682 712
 	uint32_t i;
683
-	uint64_t tmp_buffer_addr;
684
-	
713
+
685 714
 	DBGP ( "e1000_poll\n" );
686 715
 
687 716
 	/* Acknowledge interrupts */
@@ -741,46 +770,37 @@ e1000_poll ( struct net_device *netdev )
741 770
 		if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
742 771
 			break;
743 772
 
773
+		if ( adapter->rx_iobuf[i] == NULL )
774
+			break;
775
+
744 776
 		DBG ( "RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, RCTL ) );
745 777
 	
746 778
 		rx_len = rx_curr_desc->length;
747 779
 
748 780
                 DBG ( "Received packet, rx_curr: %d  rx_status: %#08x  rx_len: %d\n",
749 781
                       i, rx_status, rx_len );
750
-                
782
+
751 783
                 rx_err = rx_curr_desc->errors;
752
-                
784
+
785
+		iob_put ( adapter->rx_iobuf[i], rx_len );
786
+
753 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 790
 			DBG ( "e1000_poll: Corrupted packet received!"
757 791
 			      " rx_err: %#08x\n", rx_err );
758 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 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 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 806
  * e1000_irq - enable or Disable interrupts

Loading…
Cancel
Save