Changeset 40992 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Apr 19, 2012 1:55:42 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevE1000.cpp
r40985 r40992 31 31 #define E1kLogRel(a) 32 32 33 /* Options */ 33 /* Options *******************************************************************/ 34 /* 35 * E1K_INIT_RA0 forces E1000 to set the first entry in Receive Address filter 36 * table to MAC address obtained from CFGM. Most guests read MAC address from 37 * EEPROM and write it to RA[0] explicitly, but Mac OS X seems to depend on it 38 * being already set (see #4657). 39 */ 34 40 #define E1K_INIT_RA0 41 /* 42 * E1K_LSC_ON_SLU causes E1000 to generate Link Status Change interrupt when 43 * the guest driver brings up the link via STATUS.LU bit. Again the only guest 44 * that requires it is Mac OS X (see #4657). 45 */ 35 46 #define E1K_LSC_ON_SLU 47 /* 48 * E1K_ITR_ENABLED reduces the number of interrupts generated by E1000 if a 49 * guest driver requested it by writing non-zero value to the Interrupt 50 * Throttling Register (see section 13.4.18 in "8254x Family of Gigabit 51 * Ethernet Controllers Software Developer’s Manual"). 52 */ 36 53 #define E1K_ITR_ENABLED 37 //#define E1K_GLOBAL_MUTEX 54 /* 55 * E1K_USE_TX_TIMERS aims to reduce the number of generated TX interrupts if a 56 * guest driver set the delays via the Transmit Interrupt Delay Value (TIDV) 57 * register. Enabling it showed no positive effects on existing guests so it 58 * stays disabled. See sections 3.2.7.1 and 3.4.3.1 in "8254x Family of Gigabit 59 * Ethernet Controllers Software Developer’s Manual" for more detailed 60 * explanation. 61 */ 38 62 //#define E1K_USE_TX_TIMERS 63 /* 64 * E1K_NO_TAD disables one of two timers enabled by E1K_USE_TX_TIMERS, the 65 * Transmit Absolute Delay time. This timer sets the maximum time interval 66 * during which TX interrupts can be postponed (delayed). It has no effect 67 * if E1K_USE_TX_TIMERS is not defined. 68 */ 39 69 //#define E1K_NO_TAD 70 /* 71 * E1K_REL_DEBUG enables debug logging of l1, l2, l3 in release build. 72 */ 40 73 //#define E1K_REL_DEBUG 74 /* 75 * E1K_INT_STATS enables collection of internal statistics used for 76 * debugging of delayed interrupts, etc. 77 */ 41 78 //#define E1K_INT_STATS 42 //#define E1K_REL_STATS 43 //#define E1K_USE_SUPLIB_SEMEVENT 79 /* 80 * E1K_WITH_MSI enables rudimentary MSI support. Not implemented. 81 */ 44 82 //#define E1K_WITH_MSI 83 /* 84 * E1K_WITH_TXD_CACHE causes E1000 to fetch multiple TX descriptors in a 85 * single physical memory read (or two if it wraps around the end of TX 86 * descriptor ring). It is required for proper functioning of bandwidth 87 * resource control as it allows to compute exact sizes of packets prior 88 * to allocating their buffers (see #5582). 89 */ 45 90 #define E1K_WITH_TXD_CACHE 1 91 /* End of Options ************************************************************/ 46 92 47 93 #ifdef E1K_WITH_TXD_CACHE 94 /* 95 * E1K_TXD_CACHE_SIZE specifies the maximum number of TX descriptors stored 96 * in the state structure. It limits the amount of descriptors loaded in one 97 * batch read. For example, Windows XP guest uses about 5 descriptors per 98 * TSE packet. 99 */ 48 100 #define E1K_TXD_CACHE_SIZE 16u 49 101 #endif /* E1K_WITH_TXD_CACHE */ … … 75 127 76 128 #ifndef DEBUG 77 # ifdef E1K_REL_STATS78 # undef STAM_COUNTER_INC79 # undef STAM_PROFILE_ADV_START80 # undef STAM_PROFILE_ADV_STOP81 # define STAM_COUNTER_INC STAM_REL_COUNTER_INC82 # define STAM_PROFILE_ADV_START STAM_REL_PROFILE_ADV_START83 # define STAM_PROFILE_ADV_STOP STAM_REL_PROFILE_ADV_STOP84 # endif85 129 # ifdef E1K_REL_DEBUG 86 130 # define DEBUG … … 962 1006 #endif 963 1007 PDMCRITSECT cs; /**< Critical section - what is it protecting? */ 964 #ifndef E1K_GLOBAL_MUTEX965 1008 PDMCRITSECT csRx; /**< RX Critical section. */ 966 1009 // PDMCRITSECT csTx; /**< TX Critical section. */ 967 #endif968 1010 /** Base address of memory-mapped registers. */ 969 1011 RTGCPHYS addrMMReg; … … 1081 1123 STAMCOUNTER StatReceiveBytes; 1082 1124 STAMCOUNTER StatTransmitBytes; 1083 #if defined(VBOX_WITH_STATISTICS) || defined(E1K_REL_STATS)1125 #if defined(VBOX_WITH_STATISTICS) 1084 1126 STAMPROFILEADV StatMMIOReadRZ; 1085 1127 STAMPROFILEADV StatMMIOReadR3; … … 1116 1158 STAMCOUNTER StatPHYAccesses; 1117 1159 1118 #endif /* VBOX_WITH_STATISTICS || E1K_REL_STATS*/1160 #endif /* VBOX_WITH_STATISTICS */ 1119 1161 1120 1162 #ifdef E1K_INT_STATS … … 1437 1479 } 1438 1480 1439 #ifdef E1K_GLOBAL_MUTEX 1440 1441 DECLINLINE(int) e1kCsEnter(E1KSTATE *pState, int iBusyRc) 1442 { 1443 return VINF_SUCCESS; 1444 } 1445 1446 DECLINLINE(void) e1kCsLeave(E1KSTATE *pState) 1447 { 1448 } 1449 1450 # define e1kCsRxEnter(ps, rc) VINF_SUCCESS 1451 # define e1kCsRxLeave(ps) do { } while (0) 1452 1453 # define e1kCsTxEnter(ps, rc) VINF_SUCCESS 1454 # define e1kCsTxLeave(ps) do { } while (0) 1455 1456 1457 DECLINLINE(int) e1kMutexAcquire(E1KSTATE *pState, int iBusyRc, RT_SRC_POS_DECL) 1458 { 1459 int rc = PDMCritSectEnter(&pState->cs, iBusyRc); 1460 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 1461 { 1462 E1kLog2(("%s ==> FAILED to enter critical section at %s:%d:%s with rc=\n", 1463 INSTANCE(pState), RT_SRC_POS_ARGS, rc)); 1464 PDMDevHlpDBGFStop(pState->CTX_SUFF(pDevIns), RT_SRC_POS_ARGS, 1465 "%s Failed to enter critical section, rc=%Rrc\n", 1466 INSTANCE(pState), rc); 1467 } 1468 else 1469 { 1470 //E1kLog2(("%s ==> Mutex acquired at %s:%d:%s\n", INSTANCE(pState), RT_SRC_POS_ARGS)); 1471 } 1472 return rc; 1473 } 1474 1475 DECLINLINE(void) e1kMutexRelease(E1KSTATE *pState) 1476 { 1477 //E1kLog2(("%s <== Releasing mutex...\n", INSTANCE(pState))); 1478 PDMCritSectLeave(&pState->cs); 1479 } 1480 1481 #else /* !E1K_GLOBAL_MUTEX */ 1482 # define e1kCsEnter(ps, rc) PDMCritSectEnter(&ps->cs, rc) 1483 # define e1kCsLeave(ps) PDMCritSectLeave(&ps->cs) 1484 1485 # define e1kCsRxEnter(ps, rc) PDMCritSectEnter(&ps->csRx, rc) 1486 # define e1kCsRxLeave(ps) PDMCritSectLeave(&ps->csRx) 1487 1488 # define e1kCsTxEnter(ps, rc) VINF_SUCCESS 1489 # define e1kCsTxLeave(ps) do { } while (0) 1481 #define e1kCsEnter(ps, rc) PDMCritSectEnter(&ps->cs, rc) 1482 #define e1kCsLeave(ps) PDMCritSectLeave(&ps->cs) 1483 1484 #define e1kCsRxEnter(ps, rc) PDMCritSectEnter(&ps->csRx, rc) 1485 #define e1kCsRxLeave(ps) PDMCritSectLeave(&ps->csRx) 1486 1487 #define e1kCsTxEnter(ps, rc) VINF_SUCCESS 1488 #define e1kCsTxLeave(ps) do { } while (0) 1490 1489 //# define e1kCsTxEnter(ps, rc) PDMCritSectEnter(&ps->csTx, rc) 1491 1490 //# define e1kCsTxLeave(ps) PDMCritSectLeave(&ps->csTx) 1492 1491 1493 # if 01494 DECLINLINE(int) e1kCsEnter(E1KSTATE *pState, PPDMCRITSECT pCs, int iBusyRc, RT_SRC_POS_DECL)1495 {1496 int rc = PDMCritSectEnter(pCs, iBusyRc);1497 if (RT_FAILURE(rc))1498 {1499 E1kLog2(("%s ==> FAILED to enter critical section at %s:%d:%s with rc=%Rrc\n",1500 INSTANCE(pState), RT_SRC_POS_ARGS, rc));1501 PDMDeviceDBGFStop(pState->CTX_SUFF(pDevIns), RT_SRC_POS_ARGS,1502 "%s Failed to enter critical section, rc=%Rrc\n",1503 INSTANCE(pState), rc);1504 }1505 else1506 {1507 //E1kLog2(("%s ==> Entered critical section at %s:%d:%s\n", INSTANCE(pState), RT_SRC_POS_ARGS));1508 }1509 return RT_SUCCESS(rc);1510 }1511 1512 DECLINLINE(void) e1kCsLeave(E1KSTATE *pState, PPDMCRITSECT pCs)1513 {1514 //E1kLog2(("%s <== Leaving critical section\n", INSTANCE(pState)));1515 PDMCritSectLeave(&pState->cs);1516 }1517 # endif1518 DECLINLINE(int) e1kMutexAcquire(E1KSTATE *pState, int iBusyRc, RT_SRC_POS_DECL)1519 {1520 return VINF_SUCCESS;1521 }1522 1523 DECLINLINE(void) e1kMutexRelease(E1KSTATE *pState)1524 {1525 }1526 1527 #endif /* !E1K_GLOBAL_MUTEX */1528 1492 #ifdef IN_RING3 1529 1493 … … 1821 1785 pState->fIntRaised = true; 1822 1786 /* Raise(1) INTA(0) */ 1823 //e1kMutexRelease(pState);1824 1787 E1kLogRel(("E1000: irq RAISED icr&mask=0x%x, icr=0x%x\n", ICR & IMS, ICR)); 1825 1788 PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 1); 1826 //e1kMutexAcquire(pState, RT_SRC_POS);1827 1789 E1kLog(("%s e1kRaiseInterrupt: Raised. ICR&IMS=%08x\n", 1828 1790 INSTANCE(pState), ICR & IMS)); … … 2034 1996 uint8_t *ptr = rxPacket; 2035 1997 2036 #ifndef E1K_GLOBAL_MUTEX2037 1998 int rc = e1kCsRxEnter(pState, VERR_SEM_BUSY); 2038 1999 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 2039 2000 return rc; 2040 #endif2041 2001 2042 2002 if (cb > 70) /* unqualified guess */ … … 2507 2467 pState->fIntRaised = false; 2508 2468 /* Lower(0) INTA(0) */ 2509 //e1kMutexRelease(pState);2510 2469 PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 0); 2511 //e1kMutexAcquire(pState, RT_SRC_POS);2512 2470 2513 2471 pState->u64AckedAt = TMTimerGet(pState->CTX_SUFF(pIntTimer)); … … 2779 2737 E1KSTATE *pState = (E1KSTATE *)pvUser; 2780 2738 2781 if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS)) 2782 { 2783 E1K_INC_ISTAT_CNT(pState->uStatTID); 2784 /* Cancel absolute delay timer as we have already got attention */ 2739 E1K_INC_ISTAT_CNT(pState->uStatTID); 2740 /* Cancel absolute delay timer as we have already got attention */ 2785 2741 #ifndef E1K_NO_TAD 2786 2742 e1kCancelTimer(pState, pState->CTX_SUFF(pTADTimer)); 2787 2743 #endif /* E1K_NO_TAD */ 2788 e1kRaiseInterrupt(pState, ICR_TXDW); 2789 e1kMutexRelease(pState); 2790 } 2744 e1kRaiseInterrupt(pState, ICR_TXDW); 2791 2745 } 2792 2746 … … 2805 2759 E1KSTATE *pState = (E1KSTATE *)pvUser; 2806 2760 2807 if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS)) 2808 { 2809 E1K_INC_ISTAT_CNT(pState->uStatTAD); 2810 /* Cancel interrupt delay timer as we have already got attention */ 2811 e1kCancelTimer(pState, pState->CTX_SUFF(pTIDTimer)); 2812 e1kRaiseInterrupt(pState, ICR_TXDW); 2813 e1kMutexRelease(pState); 2814 } 2761 E1K_INC_ISTAT_CNT(pState->uStatTAD); 2762 /* Cancel interrupt delay timer as we have already got attention */ 2763 e1kCancelTimer(pState, pState->CTX_SUFF(pTIDTimer)); 2764 e1kRaiseInterrupt(pState, ICR_TXDW); 2815 2765 } 2816 2766 … … 2832 2782 E1KSTATE *pState = (E1KSTATE *)pvUser; 2833 2783 2834 if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS)) 2835 { 2836 E1K_INC_ISTAT_CNT(pState->uStatRID); 2837 /* Cancel absolute delay timer as we have already got attention */ 2838 e1kCancelTimer(pState, pState->CTX_SUFF(pRADTimer)); 2839 e1kRaiseInterrupt(pState, ICR_RXT0); 2840 e1kMutexRelease(pState); 2841 } 2784 E1K_INC_ISTAT_CNT(pState->uStatRID); 2785 /* Cancel absolute delay timer as we have already got attention */ 2786 e1kCancelTimer(pState, pState->CTX_SUFF(pRADTimer)); 2787 e1kRaiseInterrupt(pState, ICR_RXT0); 2842 2788 } 2843 2789 … … 2856 2802 E1KSTATE *pState = (E1KSTATE *)pvUser; 2857 2803 2858 if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS)) 2859 { 2860 E1K_INC_ISTAT_CNT(pState->uStatRAD); 2861 /* Cancel interrupt delay timer as we have already got attention */ 2862 e1kCancelTimer(pState, pState->CTX_SUFF(pRIDTimer)); 2863 e1kRaiseInterrupt(pState, ICR_RXT0); 2864 e1kMutexRelease(pState); 2865 } 2804 E1K_INC_ISTAT_CNT(pState->uStatRAD); 2805 /* Cancel interrupt delay timer as we have already got attention */ 2806 e1kCancelTimer(pState, pState->CTX_SUFF(pRIDTimer)); 2807 e1kRaiseInterrupt(pState, ICR_RXT0); 2866 2808 } 2867 2809 … … 2881 2823 2882 2824 STAM_PROFILE_ADV_START(&pState->StatLateIntTimer, a); 2883 if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS)) 2884 { 2885 STAM_COUNTER_INC(&pState->StatLateInts); 2886 E1K_INC_ISTAT_CNT(pState->uStatIntLate); 2825 STAM_COUNTER_INC(&pState->StatLateInts); 2826 E1K_INC_ISTAT_CNT(pState->uStatIntLate); 2887 2827 #if 0 2888 2889 2828 if (pState->iStatIntLost > -100) 2829 pState->iStatIntLost--; 2890 2830 #endif 2891 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, 0); 2892 e1kMutexRelease(pState); 2893 } 2831 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, 0); 2894 2832 STAM_PROFILE_ADV_STOP(&pState->StatLateIntTimer, a); 2895 2833 } … … 2915 2853 return; 2916 2854 2917 if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS)) 2918 { 2919 STATUS |= STATUS_LU; 2920 Phy::setLinkStatus(&pState->phy, true); 2921 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_LSC); 2922 e1kMutexRelease(pState); 2923 } 2855 STATUS |= STATUS_LU; 2856 Phy::setLinkStatus(&pState->phy, true); 2857 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_LSC); 2924 2858 } 2925 2859 … … 3420 3354 /* Release critical section to avoid deadlock in CanReceive */ 3421 3355 //e1kCsLeave(pState); 3422 e1kMutexRelease(pState);3423 3356 STAM_PROFILE_START(&pState->CTX_SUFF_Z(StatTransmitSend), a); 3424 3357 rc = pDrv->pfnSendBuf(pDrv, pSg, fOnWorkerThread); 3425 3358 STAM_PROFILE_STOP(&pState->CTX_SUFF_Z(StatTransmitSend), a); 3426 e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS);3427 3359 //e1kCsEnter(pState, RT_SRC_POS); 3428 3360 } … … 4581 4513 return rc; 4582 4514 } 4583 rc = e1kMutexAcquire(pState, VERR_TRY_AGAIN, RT_SRC_POS); 4584 if (RT_SUCCESS(rc)) 4585 { 4586 /* 4587 * Process all pending descriptors. 4588 * Note! Do not process descriptors in locked state 4589 */ 4590 while (TDH != TDT && !pState->fLocked) 4591 { 4592 E1KTXDESC desc; 4593 E1kLog3(("%s About to process new TX descriptor at %08x%08x, TDLEN=%08x, TDH=%08x, TDT=%08x\n", 4594 INSTANCE(pState), TDBAH, TDBAL + TDH * sizeof(desc), TDLEN, TDH, TDT)); 4595 4596 e1kLoadDesc(pState, &desc, ((uint64_t)TDBAH << 32) + TDBAL + TDH * sizeof(desc)); 4597 rc = e1kXmitDesc(pState, &desc, ((uint64_t)TDBAH << 32) + TDBAL + TDH * sizeof(desc), fOnWorkerThread); 4598 /* If we failed to transmit descriptor we will try it again later */ 4599 if (RT_FAILURE(rc)) 4600 break; 4601 if (++TDH * sizeof(desc) >= TDLEN) 4602 TDH = 0; 4603 4604 if (e1kGetTxLen(pState) <= GET_BITS(TXDCTL, LWTHRESH)*8) 4605 { 4606 E1kLog2(("%s Low on transmit descriptors, raise ICR.TXD_LOW, len=%x thresh=%x\n", 4607 INSTANCE(pState), e1kGetTxLen(pState), GET_BITS(TXDCTL, LWTHRESH)*8)); 4608 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_TXD_LOW); 4609 } 4610 4611 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a); 4612 } 4613 4614 /// @todo: uncomment: pState->uStatIntTXQE++; 4615 /// @todo: uncomment: e1kRaiseInterrupt(pState, ICR_TXQE); 4616 4617 /* 4618 * Release the locks. 4619 */ 4620 e1kMutexRelease(pState); 4621 } 4515 /* 4516 * Process all pending descriptors. 4517 * Note! Do not process descriptors in locked state 4518 */ 4519 while (TDH != TDT && !pState->fLocked) 4520 { 4521 E1KTXDESC desc; 4522 E1kLog3(("%s About to process new TX descriptor at %08x%08x, TDLEN=%08x, TDH=%08x, TDT=%08x\n", 4523 INSTANCE(pState), TDBAH, TDBAL + TDH * sizeof(desc), TDLEN, TDH, TDT)); 4524 4525 e1kLoadDesc(pState, &desc, ((uint64_t)TDBAH << 32) + TDBAL + TDH * sizeof(desc)); 4526 rc = e1kXmitDesc(pState, &desc, ((uint64_t)TDBAH << 32) + TDBAL + TDH * sizeof(desc), fOnWorkerThread); 4527 /* If we failed to transmit descriptor we will try it again later */ 4528 if (RT_FAILURE(rc)) 4529 break; 4530 if (++TDH * sizeof(desc) >= TDLEN) 4531 TDH = 0; 4532 4533 if (e1kGetTxLen(pState) <= GET_BITS(TXDCTL, LWTHRESH)*8) 4534 { 4535 E1kLog2(("%s Low on transmit descriptors, raise ICR.TXD_LOW, len=%x thresh=%x\n", 4536 INSTANCE(pState), e1kGetTxLen(pState), GET_BITS(TXDCTL, LWTHRESH)*8)); 4537 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_TXD_LOW); 4538 } 4539 4540 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a); 4541 } 4542 4543 /// @todo: uncomment: pState->uStatIntTXQE++; 4544 /// @todo: uncomment: e1kRaiseInterrupt(pState, ICR_TXQE); 4545 4546 /* 4547 * Release the lock. 4548 */ 4622 4549 if (pDrv) 4623 4550 pDrv->pfnEndXmit(pDrv); … … 4647 4574 return rc; 4648 4575 } 4649 rc = e1kMutexAcquire(pState, VERR_TRY_AGAIN, RT_SRC_POS); 4650 if (RT_SUCCESS(rc)) 4651 { 4652 /*size_t cbPacket = 0; 4653 int nDescInPacket = 0; 4654 E1KTXDESC *pFirstDesc = pState->aTxDescriptors;*/ 4655 /* 4656 * Process all pending descriptors. 4657 * Note! Do not process descriptors in locked state 4658 */ 4659 STAM_PROFILE_ADV_START(&pState->CTX_SUFF_Z(StatTransmit), a); 4660 while (!pState->fLocked && e1kTxDLazyLoad(pState)) 4661 { 4662 while (e1kLocateTxPacket(pState)) 4663 { 4664 // 1) packet located -- allocate it! 4665 rc = e1kXmitAllocBuf(pState, pState->fGSO); 4666 /* If we're out of bandwidth we'll come back later. */ 4667 if (RT_FAILURE(rc)) 4668 goto out; 4669 /* Copy the packet to allocated buffer and send it. */ 4670 rc = e1kXmitPacket(pState, fOnWorkerThread); 4671 /* If we're out of bandwidth we'll come back later. */ 4672 if (RT_FAILURE(rc)) 4673 goto out; 4674 } 4675 uint8_t u8Remain = pState->nTxDFetched - pState->iTxDCurrent; 4676 if (u8Remain > 0) 4677 { 4678 /* 4679 * A packet was partially fetched. Move incomplete packet to 4680 * the beginning of cache buffer, then load more descriptors. 4681 */ 4682 memmove(pState->aTxDescriptors, 4683 &pState->aTxDescriptors[pState->iTxDCurrent], 4684 u8Remain * sizeof(E1KTXDESC)); 4685 pState->nTxDFetched = u8Remain; 4686 e1kTxDLoadMore(pState); 4687 } 4688 else 4689 pState->nTxDFetched = 0; 4690 pState->iTxDCurrent = 0; 4691 } 4692 if (!pState->fLocked && GET_BITS(TXDCTL, LWTHRESH) == 0) 4693 { 4694 E1kLog2(("%s Out of transmit descriptors, raise ICR.TXD_LOW\n", 4695 INSTANCE(pState))); 4696 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_TXD_LOW); 4697 } 4576 4577 /* 4578 * Process all pending descriptors. 4579 * Note! Do not process descriptors in locked state 4580 */ 4581 STAM_PROFILE_ADV_START(&pState->CTX_SUFF_Z(StatTransmit), a); 4582 while (!pState->fLocked && e1kTxDLazyLoad(pState)) 4583 { 4584 while (e1kLocateTxPacket(pState)) 4585 { 4586 /* Found a complete packet, allocate it. */ 4587 rc = e1kXmitAllocBuf(pState, pState->fGSO); 4588 /* If we're out of bandwidth we'll come back later. */ 4589 if (RT_FAILURE(rc)) 4590 goto out; 4591 /* Copy the packet to allocated buffer and send it. */ 4592 rc = e1kXmitPacket(pState, fOnWorkerThread); 4593 /* If we're out of bandwidth we'll come back later. */ 4594 if (RT_FAILURE(rc)) 4595 goto out; 4596 } 4597 uint8_t u8Remain = pState->nTxDFetched - pState->iTxDCurrent; 4598 if (u8Remain > 0) 4599 { 4600 /* 4601 * A packet was partially fetched. Move incomplete packet to 4602 * the beginning of cache buffer, then load more descriptors. 4603 */ 4604 memmove(pState->aTxDescriptors, 4605 &pState->aTxDescriptors[pState->iTxDCurrent], 4606 u8Remain * sizeof(E1KTXDESC)); 4607 pState->nTxDFetched = u8Remain; 4608 e1kTxDLoadMore(pState); 4609 } 4610 else 4611 pState->nTxDFetched = 0; 4612 pState->iTxDCurrent = 0; 4613 } 4614 if (!pState->fLocked && GET_BITS(TXDCTL, LWTHRESH) == 0) 4615 { 4616 E1kLog2(("%s Out of transmit descriptors, raise ICR.TXD_LOW\n", 4617 INSTANCE(pState))); 4618 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_TXD_LOW); 4619 } 4698 4620 4699 4621 out: 4700 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a); 4701 4702 /// @todo: uncomment: pState->uStatIntTXQE++; 4703 /// @todo: uncomment: e1kRaiseInterrupt(pState, ICR_TXQE); 4704 4705 /* 4706 * Release the locks. 4707 */ 4708 e1kMutexRelease(pState); 4709 } 4622 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a); 4623 4624 /// @todo: uncomment: pState->uStatIntTXQE++; 4625 /// @todo: uncomment: e1kRaiseInterrupt(pState, ICR_TXQE); 4626 4627 /* 4628 * Release the lock. 4629 */ 4710 4630 if (pDrv) 4711 4631 pDrv->pfnEndXmit(pDrv); … … 5122 5042 * Mask out irrelevant bits. 5123 5043 */ 5124 #ifdef E1K_GLOBAL_MUTEX5125 rc = e1kMutexAcquire(pState, VINF_IOM_R3_MMIO_READ, RT_SRC_POS);5126 #else5127 5044 //rc = e1kCsEnter(pState, VERR_SEM_BUSY, RT_SRC_POS); 5128 #endif5129 5045 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 5130 5046 return rc; … … 5135 5051 u32 &= mask; 5136 5052 //e1kCsLeave(pState); 5137 e1kMutexRelease(pState);5138 5053 E1kLog2(("%s At %08X read %s from %s (%s)\n", 5139 5054 szInst, uOffset, e1kU32toHex(u32, mask, buf), s_e1kRegMap[index].abbrev, s_e1kRegMap[index].name)); … … 5205 5120 E1kLog2(("%s At %08X write %08X to %s (%s)\n", 5206 5121 INSTANCE(pState), uOffset, u32, s_e1kRegMap[index].abbrev, s_e1kRegMap[index].name)); 5207 #ifdef E1K_GLOBAL_MUTEX5208 rc = e1kMutexAcquire(pState, VINF_IOM_R3_MMIO_WRITE, RT_SRC_POS);5209 #else5210 5122 //rc = e1kCsEnter(pState, VERR_SEM_BUSY, RT_SRC_POS); 5211 #endif5212 5123 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 5213 5124 return rc; … … 5217 5128 rc = s_e1kRegMap[index].pfnWrite(pState, uOffset, index, u32); 5218 5129 //e1kCsLeave(pState); 5219 e1kMutexRelease(pState);5220 5130 } 5221 5131 else … … 5523 5433 size_t cb; 5524 5434 5525 if (RT_UNLIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) != VINF_SUCCESS))5526 return VERR_NET_NO_BUFFER_SPACE;5527 5435 if (RT_UNLIKELY(e1kCsRxEnter(pState, VERR_SEM_BUSY) != VINF_SUCCESS)) 5528 5436 return VERR_NET_NO_BUFFER_SPACE; … … 5551 5459 5552 5460 e1kCsRxLeave(pState); 5553 e1kMutexRelease(pState);5554 5461 return cb > 0 ? VINF_SUCCESS : VERR_NET_NO_BUFFER_SPACE; 5555 5462 } … … 5801 5708 5802 5709 STAM_PROFILE_ADV_START(&pState->StatReceive, a); 5803 rc = e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS); 5804 if (RT_LIKELY(rc == VINF_SUCCESS)) 5805 { 5806 //if (!e1kCsEnter(pState, RT_SRC_POS)) 5807 // return VERR_PERMISSION_DENIED; 5808 5809 e1kPacketDump(pState, (const uint8_t*)pvBuf, cb, "<-- Incoming"); 5810 5811 /* Update stats */ 5812 if (RT_LIKELY(e1kCsEnter(pState, VERR_SEM_BUSY) == VINF_SUCCESS)) 5813 { 5814 E1K_INC_CNT32(TPR); 5815 E1K_ADD_CNT64(TORL, TORH, cb < 64? 64 : cb); 5816 e1kCsLeave(pState); 5817 } 5818 STAM_PROFILE_ADV_START(&pState->StatReceiveFilter, a); 5819 E1KRXDST status; 5820 RT_ZERO(status); 5821 bool fPassed = e1kAddressFilter(pState, pvBuf, cb, &status); 5822 STAM_PROFILE_ADV_STOP(&pState->StatReceiveFilter, a); 5823 if (fPassed) 5824 { 5825 rc = e1kHandleRxPacket(pState, pvBuf, cb, status); 5826 } 5827 //e1kCsLeave(pState); 5828 e1kMutexRelease(pState); 5829 } 5710 5711 //if (!e1kCsEnter(pState, RT_SRC_POS)) 5712 // return VERR_PERMISSION_DENIED; 5713 5714 e1kPacketDump(pState, (const uint8_t*)pvBuf, cb, "<-- Incoming"); 5715 5716 /* Update stats */ 5717 if (RT_LIKELY(e1kCsEnter(pState, VERR_SEM_BUSY) == VINF_SUCCESS)) 5718 { 5719 E1K_INC_CNT32(TPR); 5720 E1K_ADD_CNT64(TORL, TORH, cb < 64? 64 : cb); 5721 e1kCsLeave(pState); 5722 } 5723 STAM_PROFILE_ADV_START(&pState->StatReceiveFilter, a); 5724 E1KRXDST status; 5725 RT_ZERO(status); 5726 bool fPassed = e1kAddressFilter(pState, pvBuf, cb, &status); 5727 STAM_PROFILE_ADV_STOP(&pState->StatReceiveFilter, a); 5728 if (fPassed) 5729 { 5730 rc = e1kHandleRxPacket(pState, pvBuf, cb, status); 5731 } 5732 //e1kCsLeave(pState); 5830 5733 STAM_PROFILE_ADV_STOP(&pState->StatReceive, a); 5831 5734 … … 5988 5891 return VINF_SUCCESS; 5989 5892 #if 0 5990 int rc = e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS);5991 if (RT_UNLIKELY(rc != VINF_SUCCESS))5992 return rc;5993 5893 /* 1) Prevent all threads from modifying the state and memory */ 5994 5894 //pState->fLocked = true; … … 6007 5907 /* 3) Did I forget anything? */ 6008 5908 E1kLog(("%s Locked\n", INSTANCE(pState))); 6009 e1kMutexRelease(pState);6010 5909 return VINF_SUCCESS; 6011 5910 #endif … … 6070 5969 E1KSTATE* pState = PDMINS_2_DATA(pDevIns, E1KSTATE*); 6071 5970 6072 int rc = e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS);6073 if (RT_UNLIKELY(rc != VINF_SUCCESS))6074 return rc;6075 5971 /* If VM is being powered off unlocking will result in assertions in PGM */ 6076 5972 if (PDMDevHlpGetVM(pDevIns)->enmVMState == VMSTATE_RUNNING) … … 6079 5975 E1kLog(("%s VM is not running -- remain locked\n", INSTANCE(pState))); 6080 5976 E1kLog(("%s Unlocked\n", INSTANCE(pState))); 6081 e1kMutexRelease(pState);6082 5977 return VINF_SUCCESS; 6083 5978 } … … 6206 6101 E1KSTATE* pState = PDMINS_2_DATA(pDevIns, E1KSTATE*); 6207 6102 6208 int rc = e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS);6209 if (RT_UNLIKELY(rc != VINF_SUCCESS))6210 return rc;6211 6212 6103 /* Update promiscuous mode */ 6213 6104 if (pState->pDrvR3) … … 6230 6121 e1kArmTimer(pState, pState->pLUTimerR3, 5000000); 6231 6122 } 6232 e1kMutexRelease(pState);6233 6123 return VINF_SUCCESS; 6234 6124 } … … 6449 6339 pState->hEventMoreRxDescAvail = NIL_RTSEMEVENT; 6450 6340 } 6451 #ifndef E1K_GLOBAL_MUTEX6452 6341 PDMR3CritSectDelete(&pState->csRx); 6453 6342 //PDMR3CritSectDelete(&pState->csTx); 6454 #endif6455 6343 PDMR3CritSectDelete(&pState->cs); 6456 6344 } … … 6794 6682 if (RT_FAILURE(rc)) 6795 6683 return rc; 6796 #ifndef E1K_GLOBAL_MUTEX6797 6684 rc = PDMDevHlpCritSectInit(pDevIns, &pState->csRx, RT_SRC_POS, "%sRX", pState->szInstance); 6798 6685 if (RT_FAILURE(rc)) 6799 6686 return rc; 6800 #endif6801 6687 6802 6688 /* Set PCI config registers */ … … 6809 6695 #ifdef E1K_WITH_MSI 6810 6696 PDMMSIREG aMsiReg; 6811 aMsiReg.c Vectors = 1;6812 aMsiReg.i CapOffset = 0x80;6813 aMsiReg.i NextOffset = 0x0;6814 aMsiReg. iMsiFlags = 0;6697 aMsiReg.cMsiVectors = 1; 6698 aMsiReg.iMsiCapOffset = 0x80; 6699 aMsiReg.iMsiNextOffset = 0x0; 6700 aMsiReg.fMsi64bit = false; 6815 6701 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg); 6816 6702 AssertRC(rc); … … 6949 6835 e1kHardReset(pState); 6950 6836 6951 #if defined(VBOX_WITH_STATISTICS) || defined(E1K_REL_STATS)6837 #if defined(VBOX_WITH_STATISTICS) 6952 6838 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatMMIOReadRZ, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling MMIO reads in RZ", "/Devices/E1k%d/MMIO/ReadRZ", iInstance); 6953 6839 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatMMIOReadR3, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling MMIO reads in R3", "/Devices/E1k%d/MMIO/ReadR3", iInstance); … … 6970 6856 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatRxOverflow, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling RX overflows", "/Devices/E1k%d/RxOverflow", iInstance); 6971 6857 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatRxOverflowWakeup, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Nr of RX overflow wakeups", "/Devices/E1k%d/RxOverflowWakeup", iInstance); 6972 #endif /* VBOX_WITH_STATISTICS || E1K_REL_STATS*/6858 #endif /* VBOX_WITH_STATISTICS */ 6973 6859 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Devices/E1k%d/ReceiveBytes", iInstance); 6974 #if defined(VBOX_WITH_STATISTICS) || defined(E1K_REL_STATS)6860 #if defined(VBOX_WITH_STATISTICS) 6975 6861 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitRZ, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling transmits in RZ", "/Devices/E1k%d/Transmit/TotalRZ", iInstance); 6976 6862 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitR3, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling transmits in R3", "/Devices/E1k%d/Transmit/TotalR3", iInstance); 6977 #endif /* VBOX_WITH_STATISTICS || E1K_REL_STATS*/6863 #endif /* VBOX_WITH_STATISTICS */ 6978 6864 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Devices/E1k%d/TransmitBytes", iInstance); 6979 #if defined(VBOX_WITH_STATISTICS) || defined(E1K_REL_STATS)6865 #if defined(VBOX_WITH_STATISTICS) 6980 6866 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitSendRZ, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling send transmit in RZ", "/Devices/E1k%d/Transmit/SendRZ", iInstance); 6981 6867 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitSendR3, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling send transmit in R3", "/Devices/E1k%d/Transmit/SendR3", iInstance); … … 6990 6876 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTxPathRegular, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Regular descriptor path", "/Devices/E1k%d/TxPath/Normal", iInstance); 6991 6877 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatPHYAccesses, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of PHY accesses", "/Devices/E1k%d/PHYAccesses", iInstance); 6992 #endif /* VBOX_WITH_STATISTICS || E1K_REL_STATS*/6878 #endif /* VBOX_WITH_STATISTICS */ 6993 6879 6994 6880 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.