Преглед на файлове

Added ability to break ISR processing over several calls to poll().

This will allow us to implement RX quotas.
tags/v0.9.3
Michael Brown преди 17 години
родител
ревизия
3c2cc59d25
променени са 1 файла, в които са добавени 34 реда и са изтрити 17 реда
  1. 34
    17
      src/arch/i386/drivers/net/undinet.c

+ 34
- 17
src/arch/i386/drivers/net/undinet.c Целия файл

@@ -42,6 +42,8 @@ struct undi_nic {
42 42
 	SEGOFF16_t entry;
43 43
 	/** Assigned IRQ number */
44 44
 	unsigned int irq;
45
+	/** Currently processing ISR */
46
+	int isr_processing;
45 47
 };
46 48
 
47 49
 static void undinet_close ( struct net_device *netdev );
@@ -384,24 +386,32 @@ static void undinet_poll ( struct net_device *netdev ) {
384 386
 	size_t frag_len;
385 387
 	int rc;
386 388
 
387
-	/* Do nothing unless ISR has been triggered */
388
-	if ( ! undinet_isr_triggered() )
389
-		return;
390
-
391
-	/* See if this was our interrupt */
392
-	memset ( &undi_isr, 0, sizeof ( undi_isr ) );
393
-	undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
394
-	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
395
-				   sizeof ( undi_isr ) ) ) != 0 )
396
-		return;
397
-	if ( undi_isr.FuncFlag != PXENV_UNDI_ISR_OUT_OURS )
398
-		return;
399
-
400
-	/* Send EOI */
401
-	send_eoi ( undinic->irq );
389
+	if ( ! undinic->isr_processing ) {
390
+		/* Do nothing unless ISR has been triggered */
391
+		if ( ! undinet_isr_triggered() )
392
+			return;
393
+		
394
+		/* See if this was our interrupt */
395
+		memset ( &undi_isr, 0, sizeof ( undi_isr ) );
396
+		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
397
+		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
398
+					   sizeof ( undi_isr ) ) ) != 0 )
399
+			return;
400
+		if ( undi_isr.FuncFlag != PXENV_UNDI_ISR_OUT_OURS )
401
+			return;
402
+		
403
+		/* Send EOI */
404
+		send_eoi ( undinic->irq );
405
+
406
+		/* Start ISR processing */
407
+		undinic->isr_processing = 1;
408
+		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
409
+	} else {
410
+		/* Continue ISR processing */
411
+		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
412
+	}
402 413
 
403 414
 	/* Run through the ISR loop */
404
-	undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
405 415
 	while ( 1 ) {
406 416
 		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
407 417
 					   sizeof ( undi_isr ) ) ) != 0 )
@@ -420,7 +430,8 @@ static void undinet_poll ( struct net_device *netdev ) {
420 430
 				DBGC ( undinic, "UNDINIC %p could not "
421 431
 				       "allocate %zd bytes for RX buffer\n",
422 432
 				       undinic, len );
423
-				break;
433
+				/* Fragment will be dropped */
434
+				goto done;
424 435
 			}
425 436
 			if ( frag_len > pkb_available ( pkb ) ) {
426 437
 				DBGC ( undinic, "UNDINIC %p fragment too "
@@ -437,11 +448,13 @@ static void undinet_poll ( struct net_device *netdev ) {
437 448
 			break;
438 449
 		case PXENV_UNDI_ISR_OUT_DONE:
439 450
 			/* Processing complete */
451
+			undinic->isr_processing = 0;
440 452
 			goto done;
441 453
 		default:
442 454
 			/* Should never happen */
443 455
 			DBGC ( undinic, "UNDINIC %p ISR returned invalid "
444 456
 			       "FuncFlag %04x\n", undinic, undi_isr.FuncFlag );
457
+			undinic->isr_processing = 0;
445 458
 			goto done;
446 459
 		}
447 460
 		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
@@ -505,6 +518,10 @@ static void undinet_close ( struct net_device *netdev ) {
505 518
 	struct undi_nic *undinic = netdev->priv;
506 519
 	struct s_PXENV_UNDI_CLOSE close;
507 520
 
521
+	/* Ensure ISR has exited cleanly */
522
+	while ( undinic->isr_processing )
523
+		undinet_poll ( netdev );
524
+
508 525
 	/* Close NIC */
509 526
 	undinet_call ( undinic, PXENV_UNDI_CLOSE, &close, sizeof ( close ) );
510 527
 

Loading…
Отказ
Запис