Changeset 41502 in vbox for trunk/src/VBox/Devices
- Timestamp:
- May 30, 2012 5:15:22 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 78261
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevE1000.cpp
r41431 r41502 84 84 * E1K_WITH_TX_CS protects e1kXmitPending with a critical section. 85 85 */ 86 #define E1K_WITH_TX_CS 186 #define E1K_WITH_TX_CS 87 87 /* 88 88 * E1K_WITH_TXD_CACHE causes E1000 to fetch multiple TX descriptors in a … … 92 92 * to allocating their buffers (see #5582). 93 93 */ 94 #define E1K_WITH_TXD_CACHE 1 94 #define E1K_WITH_TXD_CACHE 95 /* 96 * E1K_WITH_RXD_CACHE causes E1000 to fetch multiple RX descriptors in a 97 * single physical memory read (or two if it wraps around the end of RX 98 * descriptor ring). Intel's packet driver for DOS needs this option in 99 * order to work properly (see #6217). 100 */ 101 #define E1K_WITH_RXD_CACHE 95 102 /* End of Options ************************************************************/ 96 103 … … 104 111 #define E1K_TXD_CACHE_SIZE 32u 105 112 #endif /* E1K_WITH_TXD_CACHE */ 113 114 #ifdef E1K_WITH_RXD_CACHE 115 /* 116 * E1K_RXD_CACHE_SIZE specifies the maximum number of RX descriptors stored 117 * in the state structure. It limits the amount of descriptors loaded in one 118 * batch read. For example, XP guest adds 15 RX descriptors at a time. 119 */ 120 #define E1K_RXD_CACHE_SIZE 16u 121 #endif /* E1K_WITH_RXD_CACHE */ 106 122 107 123 #include <iprt/crc.h> … … 1077 1093 /** EMT: Gets signalled when more RX descriptors become available. */ 1078 1094 RTSEMEVENT hEventMoreRxDescAvail; 1095 #ifdef E1K_WITH_RXD_CACHE 1096 /** RX: Fetched RX descriptors. */ 1097 E1KRXDESC aRxDescriptors[E1K_RXD_CACHE_SIZE]; 1098 /** RX: Actual number of fetched RX descriptors. */ 1099 uint32_t nRxDFetched; 1100 /** RX: Index in cache of RX descriptor being processed. */ 1101 uint32_t iRxDCurrent; 1102 #endif /* E1K_WITH_RXD_CACHE */ 1079 1103 1080 1104 /** TX: Context used for TCP segmentation packets. */ … … 1552 1576 if (pState->pDrvR3) 1553 1577 pState->pDrvR3->pfnSetPromiscuousMode(pState->pDrvR3, false); 1578 1579 #ifdef E1K_WITH_TXD_CACHE 1580 int rc = e1kCsTxEnter(pState, VERR_SEM_BUSY); 1581 if (RT_LIKELY(rc == VINF_SUCCESS)) 1582 { 1583 pState->nTxDFetched = 0; 1584 pState->iTxDCurrent = 0; 1585 pState->fGSO = false; 1586 pState->cbTxAlloc = 0; 1587 e1kCsTxLeave(pState); 1588 } 1589 #endif /* E1K_WITH_TXD_CACHE */ 1590 #ifdef E1K_WITH_RXD_CACHE 1591 rc = e1kCsRxEnter(pState, VERR_SEM_BUSY); 1592 if (RT_LIKELY(rc == VINF_SUCCESS)) 1593 { 1594 pState->iRxDCurrent = pState->nRxDFetched = 0; 1595 e1kCsRxLeave(pState); 1596 } 1597 #endif /* E1K_WITH_RXD_CACHE */ 1554 1598 } 1555 1599 … … 1840 1884 } 1841 1885 1886 #ifdef E1K_WITH_RXD_CACHE 1887 /** 1888 * Return the number of RX descriptor that belong to the hardware. 1889 * 1890 * @returns the number of available descriptors in RX ring. 1891 * @param pState The device state structure. 1892 * @thread ??? 1893 */ 1894 DECLINLINE(uint32_t) e1kGetRxLen(E1KSTATE* pState) 1895 { 1896 /** 1897 * Make sure RDT won't change during computation. EMT may modify RDT at 1898 * any moment. 1899 */ 1900 uint32_t rdt = RDT; 1901 return (RDH > rdt ? RDLEN/sizeof(E1KRXDESC) : 0) + rdt - RDH; 1902 } 1903 1904 DECLINLINE(unsigned) e1kRxDInCache(E1KSTATE* pState) 1905 { 1906 return pState->nRxDFetched > pState->iRxDCurrent ? 1907 pState->nRxDFetched - pState->iRxDCurrent : 0; 1908 } 1909 1910 DECLINLINE(unsigned) e1kRxDIsCacheEmpty(E1KSTATE* pState) 1911 { 1912 return pState->iRxDCurrent >= pState->nRxDFetched; 1913 } 1914 1915 /** 1916 * Load receive descriptors from guest memory. The caller needs to be in Rx 1917 * critical section. 1918 * 1919 * We need two physical reads in case the tail wrapped around the end of RX 1920 * descriptor ring. 1921 * 1922 * @returns the actual number of descriptors fetched. 1923 * @param pState The device state structure. 1924 * @param pDesc Pointer to descriptor union. 1925 * @param addr Physical address in guest context. 1926 * @thread EMT, RX 1927 */ 1928 DECLINLINE(unsigned) e1kRxDPrefetch(E1KSTATE* pState) 1929 { 1930 /* We've already loaded pState->nRxDFetched descriptors past RDH. */ 1931 unsigned nDescsAvailable = e1kGetRxLen(pState) - e1kRxDInCache(pState); 1932 unsigned nDescsToFetch = RT_MIN(nDescsAvailable, E1K_RXD_CACHE_SIZE - pState->nRxDFetched); 1933 unsigned nDescsTotal = RDLEN / sizeof(E1KRXDESC); 1934 Assert(nDescsTotal != 0); 1935 if (nDescsTotal == 0) 1936 return 0; 1937 unsigned nFirstNotLoaded = (RDH + e1kRxDInCache(pState)) % nDescsTotal; 1938 unsigned nDescsInSingleRead = RT_MIN(nDescsToFetch, nDescsTotal - nFirstNotLoaded); 1939 E1kLog3(("%s e1kRxDPrefetch: nDescsAvailable=%u nDescsToFetch=%u " 1940 "nDescsTotal=%u nFirstNotLoaded=0x%x nDescsInSingleRead=%u\n", 1941 INSTANCE(pState), nDescsAvailable, nDescsToFetch, nDescsTotal, 1942 nFirstNotLoaded, nDescsInSingleRead)); 1943 if (nDescsToFetch == 0) 1944 return 0; 1945 E1KRXDESC* pFirstEmptyDesc = &pState->aRxDescriptors[pState->nRxDFetched]; 1946 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 1947 ((uint64_t)RDBAH << 32) + RDBAL + nFirstNotLoaded * sizeof(E1KRXDESC), 1948 pFirstEmptyDesc, nDescsInSingleRead * sizeof(E1KRXDESC)); 1949 E1kLog3(("%s Fetched %u RX descriptors at %08x%08x(0x%x), RDLEN=%08x, RDH=%08x, RDT=%08x\n", 1950 INSTANCE(pState), nDescsInSingleRead, 1951 RDBAH, RDBAL + RDH * sizeof(E1KRXDESC), 1952 nFirstNotLoaded, RDLEN, RDH, RDT)); 1953 if (nDescsToFetch > nDescsInSingleRead) 1954 { 1955 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 1956 ((uint64_t)RDBAH << 32) + RDBAL, 1957 pFirstEmptyDesc + nDescsInSingleRead, 1958 (nDescsToFetch - nDescsInSingleRead) * sizeof(E1KRXDESC)); 1959 E1kLog3(("%s Fetched %u RX descriptors at %08x%08x\n", 1960 INSTANCE(pState), nDescsToFetch - nDescsInSingleRead, 1961 RDBAH, RDBAL)); 1962 } 1963 pState->nRxDFetched += nDescsToFetch; 1964 return nDescsToFetch; 1965 } 1966 1967 DECLINLINE(E1KRXDESC*) e1kRxDGet(E1KSTATE* pState) 1968 { 1969 /* Check the cache first. */ 1970 if (pState->iRxDCurrent < pState->nRxDFetched) 1971 return &pState->aRxDescriptors[pState->iRxDCurrent++]; 1972 /* Cache is empty, reset it and check if we can fetch more. */ 1973 pState->iRxDCurrent = pState->nRxDFetched = 0; 1974 if (e1kRxDPrefetch(pState)) 1975 return &pState->aRxDescriptors[pState->iRxDCurrent++]; 1976 /* Out of Rx descriptors. */ 1977 return NULL; 1978 } 1979 #endif /* E1K_WITH_RXD_CACHE */ 1980 1842 1981 /** 1843 1982 * Advance the head pointer of the receive descriptor queue. … … 1878 2017 } 1879 2018 2019 #ifndef E1K_WITH_RXD_CACHE 1880 2020 /** 1881 2021 * Store a fragment of received packet that fits into the next available RX … … 1926 2066 STAM_PROFILE_ADV_STOP(&pState->StatReceiveStore, a); 1927 2067 } 2068 #else /* E1K_WITH_RXD_CACHE */ 2069 /** 2070 * Store a fragment of received packet at the specifed address. 2071 * 2072 * @param pState The device state structure. 2073 * @param pDesc The next available RX descriptor. 2074 * @param pvBuf The fragment. 2075 * @param cb The size of the fragment. 2076 */ 2077 static DECLCALLBACK(void) e1kStoreRxFragment(E1KSTATE *pState, E1KRXDESC *pDesc, const void *pvBuf, size_t cb) 2078 { 2079 STAM_PROFILE_ADV_START(&pState->StatReceiveStore, a); 2080 E1kLog2(("%s e1kStoreRxFragment: store fragment of %04X at %016LX, EOP=%d\n", 2081 INSTANCE(pState), cb, pDesc->u64BufAddr, pDesc->status.fEOP)); 2082 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), pDesc->u64BufAddr, pvBuf, cb); 2083 pDesc->u16Length = (uint16_t)cb; Assert(pDesc->u16Length == cb); 2084 STAM_PROFILE_ADV_STOP(&pState->StatReceiveStore, a); 2085 } 2086 #endif /* E1K_WITH_RXD_CACHE */ 1928 2087 1929 2088 /** … … 2096 2255 E1K_INC_ISTAT_CNT(pState->uStatRxFrm); 2097 2256 2257 #ifdef E1K_WITH_RXD_CACHE 2258 while (cb > 0) 2259 { 2260 E1KRXDESC *pDesc = e1kRxDGet(pState); 2261 2262 if (pDesc == NULL) 2263 { 2264 E1kLog(("%s Out of receive buffers, dropping the packet " 2265 "(cb=%u, in_cache=%u, RDH=%x RDT=%x)\n", 2266 INSTANCE(pState), cb, e1kRxDInCache(pState), RDH, RDT)); 2267 break; 2268 } 2269 #else /* !E1K_WITH_RXD_CACHE */ 2098 2270 if (RDH == RDT) 2099 2271 { 2100 E1kLog(("%s Out of receive buffers, dropping the packet ",2272 E1kLog(("%s Out of receive buffers, dropping the packet\n", 2101 2273 INSTANCE(pState))); 2102 2274 } … … 2105 2277 { 2106 2278 /* Load the descriptor pointed by head */ 2107 E1KRXDESC desc ;2279 E1KRXDESC desc, *pDesc = &desc; 2108 2280 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), e1kDescAddr(RDBAH, RDBAL, RDH), 2109 2281 &desc, sizeof(desc)); 2110 if (desc.u64BufAddr) 2282 #endif /* !E1K_WITH_RXD_CACHE */ 2283 if (pDesc->u64BufAddr) 2111 2284 { 2112 2285 /* Update descriptor */ 2113 desc.status = status;2114 desc.u16Checksum = checksum;2115 desc.status.fDD = true;2286 pDesc->status = status; 2287 pDesc->u16Checksum = checksum; 2288 pDesc->status.fDD = true; 2116 2289 2117 2290 /* … … 2119 2292 * with EMT in e1kRegWriteRDT when the write is to an unallocated 2120 2293 * page or has an access handler associated with it. 2121 * Note that it is safe to leave the critical section here since e1kRegWriteRDT() 2122 * modifies RDT only. 2294 * Note that it is safe to leave the critical section here since 2295 * e1kRegWriteRDT() never modifies RDH. It never touches already 2296 * fetched RxD cache entries either. 2123 2297 */ 2124 2298 if (cb > pState->u16RxBSize) 2125 2299 { 2126 desc.status.fEOP = false;2300 pDesc->status.fEOP = false; 2127 2301 e1kCsRxLeave(pState); 2128 e1kStoreRxFragment(pState, &desc, ptr, pState->u16RxBSize);2302 e1kStoreRxFragment(pState, pDesc, ptr, pState->u16RxBSize); 2129 2303 rc = e1kCsRxEnter(pState, VERR_SEM_BUSY); 2130 2304 if (RT_UNLIKELY(rc != VINF_SUCCESS)) … … 2135 2309 else 2136 2310 { 2137 desc.status.fEOP = true;2311 pDesc->status.fEOP = true; 2138 2312 e1kCsRxLeave(pState); 2139 e1kStoreRxFragment(pState, &desc, ptr, cb); 2313 e1kStoreRxFragment(pState, pDesc, ptr, cb); 2314 #ifdef E1K_WITH_RXD_CACHE 2315 rc = e1kCsRxEnter(pState, VERR_SEM_BUSY); 2316 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 2317 return rc; 2318 cb = 0; 2319 #else /* !E1K_WITH_RXD_CACHE */ 2140 2320 pState->led.Actual.s.fReading = 0; 2141 2321 return VINF_SUCCESS; 2322 #endif /* !E1K_WITH_RXD_CACHE */ 2142 2323 } 2143 /* Note: RDH is advanced by e1kStoreRxFragment! */ 2144 } 2324 /* 2325 * Note: RDH is advanced by e1kStoreRxFragment if E1K_WITH_RXD_CACHE 2326 * is not defined. 2327 */ 2328 } 2329 #ifndef E1K_WITH_RXD_CACHE 2145 2330 else 2146 2331 { 2147 desc.status.fDD = true; 2148 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), 2149 e1kDescAddr(RDBAH, RDBAL, RDH), 2150 &desc, sizeof(desc)); 2151 e1kAdvanceRDH(pState); 2152 } 2332 #endif /* !E1K_WITH_RXD_CACHE */ 2333 /* Write back the descriptor. */ 2334 pDesc->status.fDD = true; 2335 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), 2336 e1kDescAddr(RDBAH, RDBAL, RDH), 2337 pDesc, sizeof(E1KRXDESC)); 2338 e1kAdvanceRDH(pState); 2339 e1kPrintRDesc(pState, pDesc); 2340 #ifndef E1K_WITH_RXD_CACHE 2341 } 2342 #endif /* !E1K_WITH_RXD_CACHE */ 2153 2343 } 2154 2344 … … 2159 2349 2160 2350 e1kCsRxLeave(pState); 2351 #ifdef E1K_WITH_RXD_CACHE 2352 /* Complete packet has been stored -- it is time to let the guest know. */ 2353 # ifdef E1K_USE_RX_TIMERS 2354 if (RDTR) 2355 { 2356 /* Arm the timer to fire in RDTR usec (discard .024) */ 2357 e1kArmTimer(pState, pState->CTX_SUFF(pRIDTimer), RDTR); 2358 /* If absolute timer delay is enabled and the timer is not running yet, arm it. */ 2359 if (RADV != 0 && !TMTimerIsActive(pState->CTX_SUFF(pRADTimer))) 2360 e1kArmTimer(pState, pState->CTX_SUFF(pRADTimer), RADV); 2361 } 2362 else 2363 { 2364 # endif /* E1K_USE_RX_TIMERS */ 2365 /* 0 delay means immediate interrupt */ 2366 E1K_INC_ISTAT_CNT(pState->uStatIntRx); 2367 e1kRaiseInterrupt(pState, VERR_SEM_BUSY, ICR_RXT0); 2368 # ifdef E1K_USE_RX_TIMERS 2369 } 2370 # endif /* E1K_USE_RX_TIMERS */ 2371 #endif /* E1K_WITH_RXD_CACHE */ 2161 2372 2162 2373 return VINF_SUCCESS; … … 2698 2909 E1kLog(("%s e1kRegWriteRDT\n", INSTANCE(pState))); 2699 2910 rc = e1kRegWriteDefault(pState, offset, index, value); 2911 #ifdef E1K_WITH_RXD_CACHE 2912 /* 2913 * We need to fetch descriptors now as RDT may go whole circle 2914 * before we attempt to store a received packet. For example, 2915 * Intel's DOS drivers use 2 (!) RX descriptors with the total ring 2916 * size being only 8 descriptors! Note that we fetch descriptors 2917 * only when the cache is empty to reduce the number of memory reads 2918 * in case of frequent RDT writes. Don't fetch anything when the 2919 * receiver is disabled either as RDH, RDT, RDLEN can be in some 2920 * messed up state. 2921 * Note that despite the cache may seem empty, meaning that there are 2922 * no more available descriptors in it, it may still be used by RX 2923 * thread which has not yet written the last descriptor back but has 2924 * temporarily released the RX lock in order to write the packet body 2925 * to descriptor's buffer. At this point we still going to do prefetch 2926 * but it won't actually fetch anything if there are no unused slots in 2927 * our "empty" cache (nRxDFetched==E1K_RXD_CACHE_SIZE). We must not 2928 * reset the cache here even if it appears empty. It will be reset at 2929 * a later point in e1kRxDGet(). 2930 */ 2931 if (e1kRxDIsCacheEmpty(pState) && (RCTL & RCTL_EN)) 2932 e1kRxDPrefetch(pState); 2933 #endif /* E1K_WITH_RXD_CACHE */ 2700 2934 e1kCsRxLeave(pState); 2701 2935 if (RT_SUCCESS(rc)) … … 3172 3406 if (RT_LIKELY(GET_BITS(RCTL, LBM) != RCTL_LBM_TCVR)) 3173 3407 { 3174 Assert(pState->cbTxAlloc != 0);3175 3408 if (pState->cbTxAlloc == 0) 3176 return VERR_NET_IO_ERROR; 3409 { 3410 /* Zero packet, no need for the buffer */ 3411 return VINF_SUCCESS; 3412 } 3177 3413 3178 3414 PPDMINETWORKUP pDrv = pState->CTX_SUFF(pDrv); … … 3257 3493 DECLINLINE(unsigned) e1kTxDLoadMore(E1KSTATE* pState) 3258 3494 { 3495 Assert(pState->iTxDCurrent == 0); 3259 3496 /* We've already loaded pState->nTxDFetched descriptors past TDH. */ 3260 3497 unsigned nDescsAvailable = e1kGetTxLen(pState) - pState->nTxDFetched; … … 4261 4498 case E1K_DTYP_DATA: 4262 4499 { 4263 if (pDesc->data.cmd.u20DTALEN == 0 || pDesc->data.u64BufAddr == 0)4264 {4265 E1kLog2(("% Empty data descriptor, skipped.\n", INSTANCE(pState)));4266 /** @todo Same as legacy when !TSE. See below. */4267 break;4268 }4269 4500 STAM_COUNTER_INC(pDesc->data.cmd.fTSE? 4270 4501 &pState->StatTxDescTSEData: 4271 4502 &pState->StatTxDescData); 4272 4503 E1K_INC_ISTAT_CNT(pState->uStatDescDat); 4273 4274 /* 4275 * Add the descriptor data to the frame. If the frame is complete, 4276 * transmit it and reset the u16TxPktLen field. 4277 */ 4278 if (e1kXmitIsGsoBuf(pState->CTX_SUFF(pTxSg))) 4504 STAM_PROFILE_ADV_START(&pState->CTX_SUFF_Z(StatTransmit), a); 4505 if (pDesc->data.cmd.u20DTALEN == 0 || pDesc->data.u64BufAddr == 0) 4279 4506 { 4280 STAM_COUNTER_INC(&pState->StatTxPathGSO); 4281 bool fRc = e1kAddToFrame(pState, pDesc->data.u64BufAddr, pDesc->data.cmd.u20DTALEN); 4282 if (pDesc->data.cmd.fEOP) 4507 E1kLog2(("% Empty data descriptor, skipped.\n", INSTANCE(pState))); 4508 } 4509 else 4510 { 4511 /* 4512 * Add the descriptor data to the frame. If the frame is complete, 4513 * transmit it and reset the u16TxPktLen field. 4514 */ 4515 if (e1kXmitIsGsoBuf(pState->CTX_SUFF(pTxSg))) 4283 4516 { 4284 if ( fRc4285 && pState->CTX_SUFF(pTxSg)4286 && pState->CTX_SUFF(pTxSg)->cbUsed == (size_t)pState->contextTSE.dw3.u8HDRLEN + pState->contextTSE.dw2.u20PAYLEN)4517 STAM_COUNTER_INC(&pState->StatTxPathGSO); 4518 bool fRc = e1kAddToFrame(pState, pDesc->data.u64BufAddr, pDesc->data.cmd.u20DTALEN); 4519 if (pDesc->data.cmd.fEOP) 4287 4520 { 4521 if ( fRc 4522 && pState->CTX_SUFF(pTxSg) 4523 && pState->CTX_SUFF(pTxSg)->cbUsed == (size_t)pState->contextTSE.dw3.u8HDRLEN + pState->contextTSE.dw2.u20PAYLEN) 4524 { 4525 e1kTransmitFrame(pState, fOnWorkerThread); 4526 E1K_INC_CNT32(TSCTC); 4527 } 4528 else 4529 { 4530 if (fRc) 4531 E1kLog(("%s bad GSO/TSE %p or %u < %u\n" , INSTANCE(pState), 4532 pState->CTX_SUFF(pTxSg), pState->CTX_SUFF(pTxSg) ? pState->CTX_SUFF(pTxSg)->cbUsed : 0, 4533 pState->contextTSE.dw3.u8HDRLEN + pState->contextTSE.dw2.u20PAYLEN)); 4534 e1kXmitFreeBuf(pState); 4535 E1K_INC_CNT32(TSCTFC); 4536 } 4537 pState->u16TxPktLen = 0; 4538 } 4539 } 4540 else if (!pDesc->data.cmd.fTSE) 4541 { 4542 STAM_COUNTER_INC(&pState->StatTxPathRegular); 4543 bool fRc = e1kAddToFrame(pState, pDesc->data.u64BufAddr, pDesc->data.cmd.u20DTALEN); 4544 if (pDesc->data.cmd.fEOP) 4545 { 4546 if (fRc && pState->CTX_SUFF(pTxSg)) 4547 { 4548 Assert(pState->CTX_SUFF(pTxSg)->cSegs == 1); 4549 if (pState->fIPcsum) 4550 e1kInsertChecksum(pState, (uint8_t *)pState->CTX_SUFF(pTxSg)->aSegs[0].pvSeg, pState->u16TxPktLen, 4551 pState->contextNormal.ip.u8CSO, 4552 pState->contextNormal.ip.u8CSS, 4553 pState->contextNormal.ip.u16CSE); 4554 if (pState->fTCPcsum) 4555 e1kInsertChecksum(pState, (uint8_t *)pState->CTX_SUFF(pTxSg)->aSegs[0].pvSeg, pState->u16TxPktLen, 4556 pState->contextNormal.tu.u8CSO, 4557 pState->contextNormal.tu.u8CSS, 4558 pState->contextNormal.tu.u16CSE); 4559 e1kTransmitFrame(pState, fOnWorkerThread); 4560 } 4561 else 4562 e1kXmitFreeBuf(pState); 4563 pState->u16TxPktLen = 0; 4564 } 4565 } 4566 else 4567 { 4568 STAM_COUNTER_INC(&pState->StatTxPathFallback); 4569 rc = e1kFallbackAddToFrame(pState, pDesc, fOnWorkerThread); 4570 } 4571 } 4572 e1kDescReport(pState, pDesc, addr); 4573 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a); 4574 break; 4575 } 4576 4577 case E1K_DTYP_LEGACY: 4578 STAM_COUNTER_INC(&pState->StatTxDescLegacy); 4579 STAM_PROFILE_ADV_START(&pState->CTX_SUFF_Z(StatTransmit), a); 4580 if (pDesc->legacy.cmd.u16Length == 0 || pDesc->legacy.u64BufAddr == 0) 4581 { 4582 E1kLog(("%s Empty legacy descriptor, skipped.\n", INSTANCE(pState))); 4583 } 4584 else 4585 { 4586 /* Add fragment to frame. */ 4587 if (e1kAddToFrame(pState, pDesc->data.u64BufAddr, pDesc->legacy.cmd.u16Length)) 4588 { 4589 E1K_INC_ISTAT_CNT(pState->uStatDescLeg); 4590 4591 /* Last fragment: Transmit and reset the packet storage counter. */ 4592 if (pDesc->legacy.cmd.fEOP) 4593 { 4594 if (pDesc->legacy.cmd.fIC) 4595 { 4596 e1kInsertChecksum(pState, 4597 (uint8_t *)pState->CTX_SUFF(pTxSg)->aSegs[0].pvSeg, 4598 pState->u16TxPktLen, 4599 pDesc->legacy.cmd.u8CSO, 4600 pDesc->legacy.dw3.u8CSS, 4601 0); 4602 } 4288 4603 e1kTransmitFrame(pState, fOnWorkerThread); 4289 E1K_INC_CNT32(TSCTC);4604 pState->u16TxPktLen = 0; 4290 4605 } 4291 else 4292 { 4293 if (fRc) 4294 E1kLog(("%s bad GSO/TSE %p or %u < %u\n" , INSTANCE(pState), 4295 pState->CTX_SUFF(pTxSg), pState->CTX_SUFF(pTxSg) ? pState->CTX_SUFF(pTxSg)->cbUsed : 0, 4296 pState->contextTSE.dw3.u8HDRLEN + pState->contextTSE.dw2.u20PAYLEN)); 4297 e1kXmitFreeBuf(pState); 4298 E1K_INC_CNT32(TSCTFC); 4299 } 4606 } 4607 /* Last fragment + failure: free the buffer and reset the storage counter. */ 4608 else if (pDesc->legacy.cmd.fEOP) 4609 { 4610 e1kXmitFreeBuf(pState); 4300 4611 pState->u16TxPktLen = 0; 4301 4612 } 4302 4613 } 4303 else if (!pDesc->data.cmd.fTSE)4304 {4305 STAM_COUNTER_INC(&pState->StatTxPathRegular);4306 bool fRc = e1kAddToFrame(pState, pDesc->data.u64BufAddr, pDesc->data.cmd.u20DTALEN);4307 if (pDesc->data.cmd.fEOP)4308 {4309 if (fRc && pState->CTX_SUFF(pTxSg))4310 {4311 Assert(pState->CTX_SUFF(pTxSg)->cSegs == 1);4312 if (pState->fIPcsum)4313 e1kInsertChecksum(pState, (uint8_t *)pState->CTX_SUFF(pTxSg)->aSegs[0].pvSeg, pState->u16TxPktLen,4314 pState->contextNormal.ip.u8CSO,4315 pState->contextNormal.ip.u8CSS,4316 pState->contextNormal.ip.u16CSE);4317 if (pState->fTCPcsum)4318 e1kInsertChecksum(pState, (uint8_t *)pState->CTX_SUFF(pTxSg)->aSegs[0].pvSeg, pState->u16TxPktLen,4319 pState->contextNormal.tu.u8CSO,4320 pState->contextNormal.tu.u8CSS,4321 pState->contextNormal.tu.u16CSE);4322 e1kTransmitFrame(pState, fOnWorkerThread);4323 }4324 else4325 e1kXmitFreeBuf(pState);4326 pState->u16TxPktLen = 0;4327 }4328 }4329 else4330 {4331 STAM_COUNTER_INC(&pState->StatTxPathFallback);4332 rc = e1kFallbackAddToFrame(pState, pDesc, fOnWorkerThread);4333 }4334 4335 e1kDescReport(pState, pDesc, addr);4336 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a);4337 break;4338 }4339 4340 case E1K_DTYP_LEGACY:4341 if (pDesc->legacy.cmd.u16Length == 0 || pDesc->legacy.u64BufAddr == 0)4342 {4343 E1kLog(("%s Empty legacy descriptor, skipped.\n", INSTANCE(pState)));4344 /** @todo 3.3.3, Length/Buffer Address: RS set -> write DD when processing. */4345 break;4346 }4347 STAM_COUNTER_INC(&pState->StatTxDescLegacy);4348 STAM_PROFILE_ADV_START(&pState->CTX_SUFF_Z(StatTransmit), a);4349 4350 /* Add fragment to frame. */4351 if (e1kAddToFrame(pState, pDesc->data.u64BufAddr, pDesc->legacy.cmd.u16Length))4352 {4353 E1K_INC_ISTAT_CNT(pState->uStatDescLeg);4354 4355 /* Last fragment: Transmit and reset the packet storage counter. */4356 if (pDesc->legacy.cmd.fEOP)4357 {4358 if (pDesc->legacy.cmd.fIC)4359 {4360 e1kInsertChecksum(pState,4361 (uint8_t *)pState->CTX_SUFF(pTxSg)->aSegs[0].pvSeg,4362 pState->u16TxPktLen,4363 pDesc->legacy.cmd.u8CSO,4364 pDesc->legacy.dw3.u8CSS,4365 0);4366 }4367 e1kTransmitFrame(pState, fOnWorkerThread);4368 pState->u16TxPktLen = 0;4369 }4370 }4371 /* Last fragment + failure: free the buffer and reset the storage counter. */4372 else if (pDesc->legacy.cmd.fEOP)4373 {4374 e1kXmitFreeBuf(pState);4375 pState->u16TxPktLen = 0;4376 }4377 4378 4614 e1kDescReport(pState, pDesc, addr); 4379 4615 STAM_PROFILE_ADV_STOP(&pState->CTX_SUFF_Z(StatTransmit), a); … … 4441 4677 continue; 4442 4678 case E1K_DTYP_LEGACY: 4679 /* Skip empty descriptors. */ 4680 if (!pDesc->legacy.u64BufAddr || !pDesc->legacy.cmd.u16Length) 4681 break; 4443 4682 cbPacket += pDesc->legacy.cmd.u16Length; 4444 4683 pState->fGSO = false; 4445 4684 break; 4446 4685 case E1K_DTYP_DATA: 4686 /* Skip empty descriptors. */ 4687 if (!pDesc->data.u64BufAddr || !pDesc->data.cmd.u20DTALEN) 4688 break; 4447 4689 if (cbPacket == 0) 4448 4690 { … … 4496 4738 } 4497 4739 4740 if (cbPacket == 0 && pState->nTxDFetched - pState->iTxDCurrent > 0) 4741 { 4742 /* All descriptors were empty, we need to process them as a dummy packet */ 4743 LogFlow(("%s e1kLocateTxPacket: RET true cbTxAlloc=%d, zero packet!\n", 4744 INSTANCE(pState), pState->cbTxAlloc)); 4745 return true; 4746 } 4498 4747 LogFlow(("%s e1kLocateTxPacket: RET false cbTxAlloc=%d\n", 4499 4748 INSTANCE(pState), pState->cbTxAlloc)); … … 5537 5786 static int e1kCanReceive(E1KSTATE *pState) 5538 5787 { 5788 #ifndef E1K_WITH_RXD_CACHE 5539 5789 size_t cb; 5540 5790 … … 5566 5816 e1kCsRxLeave(pState); 5567 5817 return cb > 0 ? VINF_SUCCESS : VERR_NET_NO_BUFFER_SPACE; 5818 #else /* E1K_WITH_RXD_CACHE */ 5819 int rc = VINF_SUCCESS; 5820 5821 if (RT_UNLIKELY(e1kCsRxEnter(pState, VERR_SEM_BUSY) != VINF_SUCCESS)) 5822 return VERR_NET_NO_BUFFER_SPACE; 5823 5824 if (RT_UNLIKELY(RDLEN == sizeof(E1KRXDESC))) 5825 { 5826 E1KRXDESC desc; 5827 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), e1kDescAddr(RDBAH, RDBAL, RDH), 5828 &desc, sizeof(desc)); 5829 if (desc.status.fDD) 5830 rc = VERR_NET_NO_BUFFER_SPACE; 5831 } 5832 else if (e1kRxDIsCacheEmpty(pState) && RDH == RDT) 5833 { 5834 /* Cache is empty, so is the RX ring. */ 5835 rc = VERR_NET_NO_BUFFER_SPACE; 5836 } 5837 E1kLog2(("%s e1kCanReceive: at exit in_cache=%d RDH=%d RDT=%d RDLEN=%d" 5838 " u16RxBSize=%d rc=%Rrc\n", INSTANCE(pState), 5839 e1kRxDInCache(pState), RDH, RDT, RDLEN, pState->u16RxBSize, rc)); 5840 5841 e1kCsRxLeave(pState); 5842 return rc; 5843 #endif /* E1K_WITH_RXD_CACHE */ 5568 5844 } 5569 5845 … … 6192 6468 else 6193 6469 pState->nTxDFetched = 0; 6470 /* 6471 * @todo: Perhaps we should not store TXD cache as the entries can be 6472 * simply fetched again from guest's memory. Or can't they? 6473 */ 6194 6474 #endif /* E1K_WITH_TXD_CACHE */ 6475 #ifdef E1K_WITH_RXD_CACHE 6476 /* 6477 * There is no point in storing the RX descriptor cache in the saved 6478 * state, we just need to make sure it is empty. 6479 */ 6480 pState->iRxDCurrent = pState->nRxDFetched = 0; 6481 #endif /* E1K_WITH_RXD_CACHE */ 6195 6482 /* derived state */ 6196 6483 e1kSetupGsoCtx(&pState->GsoCtx, &pState->contextTSE); … … 6374 6661 pState->fLocked = false; 6375 6662 pState->u64AckedAt = 0; 6376 #ifdef E1K_WITH_TXD_CACHE6377 int rc = e1kCsTxEnter(pState, VERR_SEM_BUSY);6378 if (RT_LIKELY(rc == VINF_SUCCESS))6379 {6380 pState->nTxDFetched = 0;6381 pState->iTxDCurrent = 0;6382 pState->fGSO = false;6383 pState->cbTxAlloc = 0;6384 e1kCsTxLeave(pState);6385 }6386 #endif /* E1K_WITH_TXD_CACHE */6387 6663 e1kHardReset(pState); 6388 6664 }
Note:
See TracChangeset
for help on using the changeset viewer.