Changeset 41046 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Apr 24, 2012 12:38:07 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevE1000.cpp
r41034 r41046 81 81 */ 82 82 //#define E1K_WITH_MSI 83 /* 84 * E1K_WITH_TX_CS protects e1kXmitPending with a critical section. 85 */ 86 #define E1K_WITH_TX_CS 1 83 87 /* 84 88 * E1K_WITH_TXD_CACHE causes E1000 to fetch multiple TX descriptors in a … … 1010 1014 PDMCRITSECT cs; /**< Critical section - what is it protecting? */ 1011 1015 PDMCRITSECT csRx; /**< RX Critical section. */ 1012 // PDMCRITSECT csTx; /**< TX Critical section. */ 1016 #ifdef E1K_WITH_TX_CS 1017 PDMCRITSECT csTx; /**< TX Critical section. */ 1018 #endif /* E1K_WITH_TX_CS */ 1013 1019 /** Base address of memory-mapped registers. */ 1014 1020 RTGCPHYS addrMMReg; … … 1488 1494 #define e1kCsRxLeave(ps) PDMCritSectLeave(&ps->csRx) 1489 1495 1496 #ifndef E1K_WITH_TX_CS 1490 1497 #define e1kCsTxEnter(ps, rc) VINF_SUCCESS 1491 1498 #define e1kCsTxLeave(ps) do { } while (0) 1492 //# define e1kCsTxEnter(ps, rc) PDMCritSectEnter(&ps->csTx, rc) 1493 //# define e1kCsTxLeave(ps) PDMCritSectLeave(&ps->csTx) 1499 #else /* E1K_WITH_TX_CS */ 1500 # define e1kCsTxEnter(ps, rc) PDMCritSectEnter(&ps->csTx, rc) 1501 # define e1kCsTxLeave(ps) PDMCritSectLeave(&ps->csTx) 1502 #endif /* E1K_WITH_TX_CS */ 1494 1503 1495 1504 #ifdef IN_RING3 … … 3224 3233 DECLINLINE(unsigned) e1kTxDLoadMore(E1KSTATE* pState) 3225 3234 { 3226 unsigned nDescsAvailable = e1kGetTxLen(pState); 3227 unsigned nDescsToFetch = RT_MIN(nDescsAvailable, E1K_TXD_CACHE_SIZE - pState->nTxDFetched); 3228 /* 3229 * It is safe to use TDLEN and TDH in the following expression since TDLEN 3230 * is set during init and never changes after that, and TDH is advanced in 3231 * the loop we are being called from. 3232 */ 3233 unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, TDLEN / sizeof(E1KTXDESC) - TDH); 3235 /* We've already loaded pState->nTxDFetched descriptors past TDH. */ 3236 unsigned nDescsAvailable = e1kGetTxLen(pState) - pState->nTxDFetched; 3237 unsigned nDescsToFetch = RT_MIN(nDescsAvailable, E1K_TXD_CACHE_SIZE - pState->nTxDFetched); 3238 unsigned nDescsTotal = TDLEN / sizeof(E1KTXDESC); 3239 unsigned nFirstNotLoaded = (TDH + pState->nTxDFetched) % nDescsTotal; 3240 unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, nDescsTotal - nFirstNotLoaded); 3241 E1kLog3(("%s e1kTxDLoadMore: nDescsAvailable=%u nDescsToFetch=%u " 3242 "nDescsTotal=%u nFirstNotLoaded=0x%x nDescsInSingleRead=%u\n", 3243 INSTANCE(pState), nDescsAvailable, nDescsToFetch, nDescsTotal, 3244 nFirstNotLoaded, nDescsInSingleRead)); 3234 3245 if (nDescsToFetch == 0) 3235 3246 return 0; 3236 3247 E1KTXDESC* pFirstEmptyDesc = &pState->aTxDescriptors[pState->nTxDFetched]; 3237 3248 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 3238 ((uint64_t)TDBAH << 32) + TDBAL + TDH* sizeof(E1KTXDESC),3249 ((uint64_t)TDBAH << 32) + TDBAL + nFirstNotLoaded * sizeof(E1KTXDESC), 3239 3250 pFirstEmptyDesc, nDescsInSingleRead * sizeof(E1KTXDESC)); 3240 E1kLog3(("%s Fetched %u TX descriptors at %08x%08x, TDLEN=%08x, TDH=%08x, TDT=%08x\n", 3241 INSTANCE(pState), nDescsInSingleRead, TDBAH, TDBAL + TDH * sizeof(E1KTXDESC), TDLEN, TDH, TDT)); 3251 E1kLog3(("%s Fetched %u TX descriptors at %08x%08x(0x%x), TDLEN=%08x, TDH=%08x, TDT=%08x\n", 3252 INSTANCE(pState), nDescsInSingleRead, 3253 TDBAH, TDBAL + TDH * sizeof(E1KTXDESC), 3254 nFirstNotLoaded, TDLEN, TDH, TDT)); 3242 3255 if (nDescsToFetch > nDescsInSingleRead) 3243 3256 { … … 3246 3259 pFirstEmptyDesc + nDescsInSingleRead, 3247 3260 (nDescsToFetch - nDescsInSingleRead) * sizeof(E1KTXDESC)); 3248 E1kLog3(("%s Fetched %u TX descriptors at %08x%08x , TDLEN=%08x, TDH=%08x, TDT=%08x\n",3261 E1kLog3(("%s Fetched %u TX descriptors at %08x%08x\n", 3249 3262 INSTANCE(pState), nDescsToFetch - nDescsInSingleRead, 3250 TDBAH, TDBAL , TDLEN, TDH, TDT));3263 TDBAH, TDBAL)); 3251 3264 } 3252 3265 pState->nTxDFetched += nDescsToFetch; … … 4513 4526 int rc = VINF_SUCCESS; 4514 4527 4528 /* Check if transmitter is enabled. */ 4529 if (!(TCTL & TCTL_EN)) 4530 return VINF_SUCCESS; 4515 4531 /* 4516 4532 * Grab the xmit lock of the driver as well as the E1K device state. … … 4523 4539 return rc; 4524 4540 } 4525 //rc = e1kCsTxEnter(pState, VERR_SEM_BUSY);4541 rc = e1kCsTxEnter(pState, VERR_SEM_BUSY); 4526 4542 if (RT_LIKELY(rc == VINF_SUCCESS)) 4527 4543 { … … 4556 4572 /// @todo: uncomment: pState->uStatIntTXQE++; 4557 4573 /// @todo: uncomment: e1kRaiseInterrupt(pState, ICR_TXQE); 4558 //e1kCsTxLeave(pState);4574 e1kCsTxLeave(pState); 4559 4575 } 4560 4576 … … 4585 4601 int rc = VINF_SUCCESS; 4586 4602 4603 /* Check if transmitter is enabled. */ 4604 if (!(TCTL & TCTL_EN)) 4605 return VINF_SUCCESS; 4587 4606 /* 4588 4607 * Grab the xmit lock of the driver as well as the E1K device state. … … 4600 4619 * Note! Do not process descriptors in locked state 4601 4620 */ 4602 STAM_PROFILE_ADV_START(&pState->CTX_SUFF_Z(StatTransmit), a); 4603 while (!pState->fLocked && e1kTxDLazyLoad(pState)) 4604 { 4605 while (e1kLocateTxPacket(pState)) 4606 { 4607 /* Found a complete packet, allocate it. */ 4608 rc = e1kXmitAllocBuf(pState, pState->fGSO); 4609 /* If we're out of bandwidth we'll come back later. */ 4610 if (RT_FAILURE(rc)) 4621 rc = e1kCsTxEnter(pState, VERR_SEM_BUSY); 4622 if (RT_LIKELY(rc == VINF_SUCCESS)) 4623 { 4624 STAM_PROFILE_ADV_START(&pState->CTX_SUFF_Z(StatTransmit), a); 4625 /* 4626 * fIncomplete is set whenever we try to fetch additional descriptors 4627 * for an incomplete packet. If fail to locate a complete packet on 4628 * the next iteration we need to reset the cache or we risk to get 4629 * stuck in this loop forever. 4630 */ 4631 bool fIncomplete = false; 4632 while (!pState->fLocked && e1kTxDLazyLoad(pState)) 4633 { 4634 while (e1kLocateTxPacket(pState)) 4635 { 4636 fIncomplete = false; 4637 /* Found a complete packet, allocate it. */ 4638 rc = e1kXmitAllocBuf(pState, pState->fGSO); 4639 /* If we're out of bandwidth we'll come back later. */ 4640 if (RT_FAILURE(rc)) 4641 goto out; 4642 /* Copy the packet to allocated buffer and send it. */ 4643 rc = e1kXmitPacket(pState, fOnWorkerThread); 4644 /* If we're out of bandwidth we'll come back later. */ 4645 if (RT_FAILURE(rc)) 4646 goto out; 4647 } 4648 uint8_t u8Remain = pState->nTxDFetched - pState->iTxDCurrent; 4649 if (RT_UNLIKELY(fIncomplete)) 4650 { 4651 /* 4652 * The descriptor cache is full, but we were unable to find 4653 * a complete packet in it. Drop the cache and hope that 4654 * the guest driver can recover from network card error. 4655 */ 4656 LogRel(("%s No complete packets in%s TxD cache! " 4657 "Fetched=%d, current=%d, TX len=%d.\n", 4658 INSTANCE(pState), 4659 u8Remain == E1K_TXD_CACHE_SIZE ? " full" : "", 4660 pState->nTxDFetched, pState->iTxDCurrent, 4661 e1kGetTxLen(pState))); 4662 Log4(("%s No complete packets in%s TxD cache! " 4663 "Fetched=%d, current=%d, TX len=%d. Dump follows:\n", 4664 INSTANCE(pState), 4665 u8Remain == E1K_TXD_CACHE_SIZE ? " full" : "", 4666 pState->nTxDFetched, pState->iTxDCurrent, 4667 e1kGetTxLen(pState))); 4668 e1kDumpTxDCache(pState); 4669 pState->iTxDCurrent = pState->nTxDFetched = 0; 4670 rc = VERR_NET_IO_ERROR; 4611 4671 goto out; 4612 /* Copy the packet to allocated buffer and send it. */ 4613 rc = e1kXmitPacket(pState, fOnWorkerThread); 4614 /* If we're out of bandwidth we'll come back later. */ 4615 if (RT_FAILURE(rc)) 4616 goto out; 4617 } 4618 uint8_t u8Remain = pState->nTxDFetched - pState->iTxDCurrent; 4619 if (RT_UNLIKELY(u8Remain == E1K_TXD_CACHE_SIZE)) 4620 { 4621 /* 4622 * The descriptor cache is full, but we were unable to find 4623 * a complete packet in it. Drop the cache and hope that 4624 * the guest driver can recover from network card error. 4625 */ 4626 Log4(("%s No complete packets in full TxD cache! " 4627 "Fetched=%d, TX len=%d. Dump follows:\n", 4628 INSTANCE(pState), pState->nTxDFetched, e1kGetTxLen(pState))); 4629 e1kDumpTxDCache(pState); 4630 pState->nTxDFetched = 0; 4631 rc = VERR_NET_IO_ERROR; 4632 goto out; 4633 } 4634 if (u8Remain > 0) 4635 { 4636 /* 4637 * A packet was partially fetched. Move incomplete packet to 4638 * the beginning of cache buffer, then load more descriptors. 4639 */ 4640 memmove(pState->aTxDescriptors, 4641 &pState->aTxDescriptors[pState->iTxDCurrent], 4642 u8Remain * sizeof(E1KTXDESC)); 4643 pState->nTxDFetched = u8Remain; 4644 e1kTxDLoadMore(pState); 4645 } 4646 else 4647 pState->nTxDFetched = 0; 4648 pState->iTxDCurrent = 0; 4649 } 4650 if (!pState->fLocked && GET_BITS(TXDCTL, LWTHRESH) == 0) 4651 { 4652 E1kLog2(("%s Out of transmit descriptors, raise ICR.TXD_LOW\n", 4653 INSTANCE(pState))); 4654 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_TXD_LOW); 4655 } 4656 4672 } 4673 if (u8Remain > 0) 4674 { 4675 Log4(("%s Incomplete packet at %d. Already fetched %d, " 4676 "%d more are available\n", 4677 INSTANCE(pState), pState->iTxDCurrent, u8Remain, 4678 e1kGetTxLen(pState) - u8Remain)); 4679 4680 /* 4681 * A packet was partially fetched. Move incomplete packet to 4682 * the beginning of cache buffer, then load more descriptors. 4683 */ 4684 memmove(pState->aTxDescriptors, 4685 &pState->aTxDescriptors[pState->iTxDCurrent], 4686 u8Remain * sizeof(E1KTXDESC)); 4687 pState->nTxDFetched = u8Remain; 4688 e1kTxDLoadMore(pState); 4689 fIncomplete = true; 4690 } 4691 else 4692 pState->nTxDFetched = 0; 4693 pState->iTxDCurrent = 0; 4694 } 4695 if (!pState->fLocked && GET_BITS(TXDCTL, LWTHRESH) == 0) 4696 { 4697 E1kLog2(("%s Out of transmit descriptors, raise ICR.TXD_LOW\n", 4698 INSTANCE(pState))); 4699 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_TXD_LOW); 4700 } 4657 4701 out: 4658 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a); 4659 4660 /// @todo: uncomment: pState->uStatIntTXQE++; 4661 /// @todo: uncomment: e1kRaiseInterrupt(pState, ICR_TXQE); 4702 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a); 4703 4704 /// @todo: uncomment: pState->uStatIntTXQE++; 4705 /// @todo: uncomment: e1kRaiseInterrupt(pState, ICR_TXQE); 4706 4707 e1kCsTxLeave(pState); 4708 } 4709 4662 4710 4663 4711 /* … … 4727 4775 static int e1kRegWriteTDT(E1KSTATE* pState, uint32_t offset, uint32_t index, uint32_t value) 4728 4776 { 4729 int rc = e1kCsTxEnter(pState, VINF_IOM_R3_MMIO_WRITE); 4730 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 4731 return rc; 4732 rc = e1kRegWriteDefault(pState, offset, index, value); 4777 int rc = e1kRegWriteDefault(pState, offset, index, value); 4733 4778 4734 4779 /* All descriptors starting with head and not including tail belong to us. */ … … 4743 4788 E1kLog(("%s e1kRegWriteTDT: %d descriptors to process\n", 4744 4789 INSTANCE(pState), e1kGetTxLen(pState))); 4745 e1kCsTxLeave(pState);4746 4790 4747 4791 /* Transmit pending packets if possible, defer it if we cannot do it … … 4760 4804 if (rc == VERR_TRY_AGAIN) 4761 4805 rc = VINF_SUCCESS; 4806 else if (rc == VERR_SEM_BUSY) 4807 rc = VINF_IOM_R3_IOPORT_WRITE; 4762 4808 AssertRC(rc); 4763 4809 } 4764 4810 } 4765 else4766 e1kCsTxLeave(pState);4767 4811 4768 4812 return rc; … … 6298 6342 pState->u64AckedAt = 0; 6299 6343 #ifdef E1K_WITH_TXD_CACHE 6300 pState->nTxDFetched = 0; 6301 pState->iTxDCurrent = 0; 6302 pState->fGSO = false; 6303 pState->cbTxAlloc = 0; 6344 int rc = e1kCsTxEnter(pState, VERR_SEM_BUSY); 6345 if (RT_LIKELY(rc == VINF_SUCCESS)) 6346 { 6347 pState->nTxDFetched = 0; 6348 pState->iTxDCurrent = 0; 6349 pState->fGSO = false; 6350 pState->cbTxAlloc = 0; 6351 e1kCsTxLeave(pState); 6352 } 6304 6353 #endif /* E1K_WITH_TXD_CACHE */ 6305 6354 e1kHardReset(pState); … … 6375 6424 pState->hEventMoreRxDescAvail = NIL_RTSEMEVENT; 6376 6425 } 6426 #ifdef E1K_WITH_TX_CS 6427 PDMR3CritSectDelete(&pState->csTx); 6428 #endif /* E1K_WITH_TX_CS */ 6377 6429 PDMR3CritSectDelete(&pState->csRx); 6378 //PDMR3CritSectDelete(&pState->csTx);6379 6430 PDMR3CritSectDelete(&pState->cs); 6380 6431 } … … 6721 6772 if (RT_FAILURE(rc)) 6722 6773 return rc; 6774 #ifdef E1K_WITH_TX_CS 6775 rc = PDMDevHlpCritSectInit(pDevIns, &pState->csTx, RT_SRC_POS, "%sTX", pState->szInstance); 6776 if (RT_FAILURE(rc)) 6777 return rc; 6778 #endif /* E1K_WITH_TX_CS */ 6723 6779 6724 6780 /* Set PCI config registers */
Note:
See TracChangeset
for help on using the changeset viewer.