Changeset 38878 in vbox
- Timestamp:
- Sep 27, 2011 9:07:07 AM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 74200
- Location:
- trunk
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pdmdrv.h
r37418 r38878 1263 1263 PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete, 1264 1264 PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue, 1265 PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard, 1265 1266 const char *pcszId)); 1266 1267 … … 1720 1721 PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete, 1721 1722 PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue, 1723 PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard, 1722 1724 const char *pcszId) 1723 1725 { 1724 return pDrvIns->pHlpR3->pfnBlkCacheRetain(pDrvIns, ppBlkCache, pfnXferComplete, pfnXferEnqueue, p cszId);1726 return pDrvIns->pHlpR3->pfnBlkCacheRetain(pDrvIns, ppBlkCache, pfnXferComplete, pfnXferEnqueue, pfnXferEnqueueDiscard, pcszId); 1725 1727 } 1726 1728 -
trunk/include/VBox/vmm/pdmifs.h
r38622 r38878 913 913 914 914 915 /**916 * PDM range.917 */918 typedef struct PDMRANGE919 {920 /** Start offset. */921 uint64_t offStart;922 /** Size. */923 size_t cbRange;924 } PDMRANGE;925 /** Pointer to a PDM range. */926 typedef PDMRANGE *PPDMRANGE;927 928 929 915 /** Pointer to a block interface. */ 930 916 typedef struct PDMIBLOCK *PPDMIBLOCK; … … 1043 1029 * @thread Any thread. 1044 1030 */ 1045 DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIBLOCK pInterface, P PDMRANGE paRanges, unsigned cRanges));1031 DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIBLOCK pInterface, PCRTRANGE paRanges, unsigned cRanges)); 1046 1032 } PDMIBLOCK; 1047 1033 /** PDMIBLOCK interface ID. */ … … 1341 1327 * @thread Any thread. 1342 1328 */ 1343 DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIMEDIA pInterface, P PDMRANGE paRanges, unsigned cRanges));1329 DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges)); 1344 1330 1345 1331 } PDMIMEDIA; … … 1525 1511 DECLR3CALLBACKMEMBER(int, pfnStartFlush,(PPDMIBLOCKASYNC pInterface, void *pvUser)); 1526 1512 1513 /** 1514 * Discards the given range. 1515 * 1516 * @returns VBox status code. 1517 * @param pInterface Pointer to the interface structure containing the called function pointer. 1518 * @param paRanges Array of ranges to discard. 1519 * @param cRanges Number of entries in the array. 1520 * @param pvUser User argument which is returned in completion callback. 1521 * @thread Any thread. 1522 */ 1523 DECLR3CALLBACKMEMBER(int, pfnStartDiscard,(PPDMIBLOCKASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser)); 1524 1527 1525 } PDMIBLOCKASYNC; 1528 1526 /** PDMIBLOCKASYNC interface ID. */ 1529 #define PDMIBLOCKASYNC_IID " 78302d0d-4978-498c-be3c-8989cb5ff5c8"1527 #define PDMIBLOCKASYNC_IID "a921dd96-1748-4ecd-941e-d5f3cd4c8fe4" 1530 1528 1531 1529 … … 1599 1597 DECLR3CALLBACKMEMBER(int, pfnStartFlush,(PPDMIMEDIAASYNC pInterface, void *pvUser)); 1600 1598 1599 /** 1600 * Discards the given range. 1601 * 1602 * @returns VBox status code. 1603 * @param pInterface Pointer to the interface structure containing the called function pointer. 1604 * @param paRanges Array of ranges to discard. 1605 * @param cRanges Number of entries in the array. 1606 * @param pvUser User argument which is returned in completion callback. 1607 * @thread Any thread. 1608 */ 1609 DECLR3CALLBACKMEMBER(int, pfnStartDiscard,(PPDMIMEDIAASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser)); 1610 1601 1611 } PDMIMEDIAASYNC; 1602 1612 /** PDMIMEDIAASYNC interface ID. */ 1603 #define PDMIMEDIAASYNC_IID " 3553227d-714d-4d28-b993-59f4e671588e"1613 #define PDMIMEDIAASYNC_IID "4be209d3-ccb5-4297-82fe-7d8018bc6ab4" 1604 1614 1605 1615 -
trunk/include/VBox/vscsi.h
r38680 r38878 95 95 typedef VSCSILUNTYPE *PVSCSILUNTYPE; 96 96 97 /**98 * Range descriptor.99 */100 typedef struct VSCSIRANGE101 {102 /** Start offset. */103 uint64_t offStart;104 /** Size of the range. */105 size_t cbRange;106 } VSCSIRANGE;107 /** Pointer to a range descriptor. */108 typedef VSCSIRANGE *PVSCSIRANGE;109 110 97 /** The LUN can handle the UNMAP command. */ 111 98 #define VSCSI_LUN_FEATURE_UNMAP RT_BIT(0) … … 326 313 * @param pcRanges Where to store the number of ranges on success. 327 314 */ 328 VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, P VSCSIRANGE *ppaRanges,315 VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PCRTRANGE *ppaRanges, 329 316 unsigned *pcRanges); 330 317 -
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r38838 r38878 329 329 PFNAHCIPOSTPROCESS pfnPostProcess; 330 330 /** Pointer to the array of PDM ranges. */ 331 P PDMRANGEpaRanges;331 PRTRANGE paRanges; 332 332 /** Number of entries in the array. */ 333 333 unsigned cRanges; … … 3076 3076 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */ 3077 3077 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */ 3078 if (pAhciPort->pDrvBlock->pfnDiscard) 3078 if ( pAhciPort->pDrvBlock->pfnDiscard 3079 || ( pAhciPort->fAsyncInterface 3080 && pAhciPort->pDrvBlockAsync->pfnStartDiscard)) 3079 3081 { 3080 3082 p[80] = RT_H2LE_U16(0x1f0); /* support everything up to ATA/ATAPI-8 ACS */ … … 3101 3103 p[217] = RT_H2LE_U16(1); /* Non-rotational medium */ 3102 3104 3103 if (pAhciPort->pDrvBlock->pfnDiscard) /** @todo: Set bit 14 in word 69 too? (Deterministic read after TRIM). */ 3105 if ( pAhciPort->pDrvBlock->pfnDiscard 3106 || ( pAhciPort->fAsyncInterface 3107 && pAhciPort->pDrvBlockAsync->pfnStartDiscard)) /** @todo: Set bit 14 in word 69 too? (Deterministic read after TRIM). */ 3104 3108 p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */ 3105 3109 … … 5348 5352 pAhciPortTaskState->paSGEntries[0].u.temp.pvBuf = pAhciPortTaskState->pvBufferUnaligned; 5349 5353 5350 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE) 5354 if ( pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE 5355 || pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM) 5351 5356 ahciCopyFromSGListIntoBuffer(pDevIns, &pAhciPortTaskState->paSGEntries[0]); 5352 5357 … … 6076 6081 6077 6082 /** 6078 * Complete a data transfer task by freeing all occupied resources6079 * and notifying the guest.6080 *6081 * @returns VBox status code6082 *6083 * @param pAhciPort Pointer to the port where to request completed.6084 * @param pAhciPortTaskState Pointer to the task which finished.6085 * @param rcReq IPRT status code of the completed request.6086 */6087 static int ahciTransferComplete(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, int rcReq)6088 {6089 bool fXchg = false;6090 bool fRedo = false;6091 6092 ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);6093 6094 if (fXchg)6095 {6096 /* Free system resources occupied by the scatter gather list. */6097 if (pAhciPortTaskState->enmTxDir != AHCITXDIR_FLUSH)6098 ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);6099 6100 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ)6101 {6102 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciPortTaskState->cbTransfer);6103 pAhciPort->Led.Actual.s.fReading = 0;6104 }6105 else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE)6106 {6107 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciPortTaskState->cbTransfer);6108 pAhciPort->Led.Actual.s.fWriting = 0;6109 }6110 6111 if (RT_FAILURE(rcReq))6112 {6113 /* Log the error. */6114 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)6115 {6116 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH)6117 LogRel(("AHCI#%u: Flush returned rc=%Rrc\n",6118 pAhciPort->iLUN, rcReq));6119 else6120 LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",6121 pAhciPort->iLUN,6122 pAhciPortTaskState->enmTxDir == AHCITXDIR_READ6123 ? "Read"6124 : "Write",6125 pAhciPortTaskState->uOffset,6126 pAhciPortTaskState->cbTransfer, rcReq));6127 }6128 6129 fRedo = ahciIsRedoSetWarning(pAhciPort, rcReq);6130 if (!fRedo)6131 {6132 pAhciPortTaskState->cmdHdr.u32PRDBC = 0;6133 pAhciPortTaskState->uATARegError = ID_ERR;6134 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;6135 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciPortTaskState, NULL);6136 }6137 else6138 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));6139 }6140 else6141 {6142 pAhciPortTaskState->cmdHdr.u32PRDBC = pAhciPortTaskState->cbTransfer;6143 6144 pAhciPortTaskState->uATARegError = 0;6145 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;6146 6147 /* Write updated command header into memory of the guest. */6148 PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr,6149 &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));6150 }6151 6152 /* Add the task to the cache. */6153 ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhciPortTaskState->uTag], pAhciPortTaskState);6154 ASMAtomicDecU32(&pAhciPort->cTasksActive);6155 6156 if (!fRedo)6157 {6158 if (pAhciPortTaskState->fQueued)6159 {6160 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIPORTTASKSTATE))6161 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));6162 6163 /*6164 * Always raise an interrupt after task completion; delaying6165 * this (interrupt coalescing) increases latency and has a significant6166 * impact on performance (see #5071)6167 */6168 ahciSendSDBFis(pAhciPort, 0, true);6169 }6170 else6171 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, true);6172 }6173 }6174 else6175 {6176 /*6177 * Task was canceled, do the cleanup but DO NOT access the guest memory!6178 * The guest might use it for other things now because it doesn't know about that task anymore.6179 */6180 AssertMsg(pAhciPortTaskState->enmTxState == AHCITXSTATE_CANCELED,6181 ("Task is not active but wasn't canceled!\n"));6182 6183 ahciScatterGatherListFree(pAhciPortTaskState);6184 6185 /* Leave a log message about the canceled request. */6186 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)6187 {6188 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH)6189 LogRel(("AHCI#%u: Canceled flush returned rc=%Rrc\n",6190 pAhciPort->iLUN, rcReq));6191 else6192 LogRel(("AHCI#%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n",6193 pAhciPort->iLUN,6194 pAhciPortTaskState->enmTxDir == AHCITXDIR_READ6195 ? "read"6196 : "write",6197 pAhciPortTaskState->uOffset,6198 pAhciPortTaskState->cbTransfer, rcReq));6199 }6200 6201 /* Finally free the task state structure because it is completely unused now. */6202 RTMemFree(pAhciPortTaskState);6203 }6204 6205 return VINF_SUCCESS;6206 }6207 6208 /**6209 * Notification callback for a completed transfer.6210 *6211 * @returns VBox status code.6212 * @param pInterface Pointer to the interface.6213 * @param pvUser User data.6214 * @param rcReq IPRT Status code of the completed request.6215 */6216 static DECLCALLBACK(int) ahciTransferCompleteNotify(PPDMIBLOCKASYNCPORT pInterface, void *pvUser, int rcReq)6217 {6218 PAHCIPort pAhciPort = PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface);6219 PAHCIPORTTASKSTATE pAhciPortTaskState = (PAHCIPORTTASKSTATE)pvUser;6220 6221 ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n",6222 __FUNCTION__, pInterface, pvUser, pAhciPortTaskState->uTag));6223 6224 int rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rcReq);6225 6226 if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)6227 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);6228 return rc;6229 }6230 6231 /**6232 6083 * Creates the array of ranges to trim. 6233 6084 * … … 6277 6128 AssertReturn(cRanges != 0, VERR_INVALID_PARAMETER); 6278 6129 6279 pAhciPortTaskState->paRanges = (P PDMRANGE)RTMemAllocZ(sizeof(PDMRANGE) * cRanges);6130 pAhciPortTaskState->paRanges = (PRTRANGE)RTMemAllocZ(sizeof(RTRANGE) * cRanges); 6280 6131 if (pAhciPortTaskState->paRanges) 6281 6132 { … … 6309 6160 } 6310 6161 6162 /** 6163 * Destroy the trim range list. 6164 * 6165 * @returns nothing. 6166 * @param pAhciPortTaskState The task state. 6167 */ 6311 6168 static void ahciTrimRangesDestroy(PAHCIPORTTASKSTATE pAhciPortTaskState) 6312 6169 { 6313 6170 RTMemFree(pAhciPortTaskState->paRanges); 6171 } 6172 6173 /** 6174 * Complete a data transfer task by freeing all occupied resources 6175 * and notifying the guest. 6176 * 6177 * @returns VBox status code 6178 * 6179 * @param pAhciPort Pointer to the port where to request completed. 6180 * @param pAhciPortTaskState Pointer to the task which finished. 6181 * @param rcReq IPRT status code of the completed request. 6182 */ 6183 static int ahciTransferComplete(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, int rcReq) 6184 { 6185 bool fXchg = false; 6186 bool fRedo = false; 6187 6188 ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg); 6189 6190 if (fXchg) 6191 { 6192 /* Free system resources occupied by the scatter gather list. */ 6193 if (pAhciPortTaskState->enmTxDir != AHCITXDIR_FLUSH) 6194 ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState); 6195 6196 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ) 6197 { 6198 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciPortTaskState->cbTransfer); 6199 pAhciPort->Led.Actual.s.fReading = 0; 6200 } 6201 else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE) 6202 { 6203 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciPortTaskState->cbTransfer); 6204 pAhciPort->Led.Actual.s.fWriting = 0; 6205 } 6206 else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM) 6207 { 6208 ahciTrimRangesDestroy(pAhciPortTaskState); 6209 pAhciPort->Led.Actual.s.fWriting = 0; 6210 } 6211 6212 if (RT_FAILURE(rcReq)) 6213 { 6214 /* Log the error. */ 6215 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS) 6216 { 6217 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH) 6218 LogRel(("AHCI#%u: Flush returned rc=%Rrc\n", 6219 pAhciPort->iLUN, rcReq)); 6220 else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM) 6221 LogRel(("AHCI#%u: Trim returned rc=%Rrc\n", 6222 pAhciPort->iLUN, rcReq)); 6223 else 6224 LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n", 6225 pAhciPort->iLUN, 6226 pAhciPortTaskState->enmTxDir == AHCITXDIR_READ 6227 ? "Read" 6228 : "Write", 6229 pAhciPortTaskState->uOffset, 6230 pAhciPortTaskState->cbTransfer, rcReq)); 6231 } 6232 6233 fRedo = ahciIsRedoSetWarning(pAhciPort, rcReq); 6234 if (!fRedo) 6235 { 6236 pAhciPortTaskState->cmdHdr.u32PRDBC = 0; 6237 pAhciPortTaskState->uATARegError = ID_ERR; 6238 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 6239 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciPortTaskState, NULL); 6240 } 6241 else 6242 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag)); 6243 } 6244 else 6245 { 6246 pAhciPortTaskState->cmdHdr.u32PRDBC = pAhciPortTaskState->cbTransfer; 6247 6248 pAhciPortTaskState->uATARegError = 0; 6249 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK; 6250 6251 /* Write updated command header into memory of the guest. */ 6252 PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr, 6253 &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr)); 6254 } 6255 6256 /* Add the task to the cache. */ 6257 ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhciPortTaskState->uTag], pAhciPortTaskState); 6258 ASMAtomicDecU32(&pAhciPort->cTasksActive); 6259 6260 if (!fRedo) 6261 { 6262 if (pAhciPortTaskState->fQueued) 6263 { 6264 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIPORTTASKSTATE)) 6265 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag)); 6266 6267 /* 6268 * Always raise an interrupt after task completion; delaying 6269 * this (interrupt coalescing) increases latency and has a significant 6270 * impact on performance (see #5071) 6271 */ 6272 ahciSendSDBFis(pAhciPort, 0, true); 6273 } 6274 else 6275 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, true); 6276 } 6277 } 6278 else 6279 { 6280 /* 6281 * Task was canceled, do the cleanup but DO NOT access the guest memory! 6282 * The guest might use it for other things now because it doesn't know about that task anymore. 6283 */ 6284 AssertMsg(pAhciPortTaskState->enmTxState == AHCITXSTATE_CANCELED, 6285 ("Task is not active but wasn't canceled!\n")); 6286 6287 ahciScatterGatherListFree(pAhciPortTaskState); 6288 6289 /* Leave a log message about the canceled request. */ 6290 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS) 6291 { 6292 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH) 6293 LogRel(("AHCI#%u: Canceled flush returned rc=%Rrc\n", 6294 pAhciPort->iLUN, rcReq)); 6295 else 6296 LogRel(("AHCI#%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n", 6297 pAhciPort->iLUN, 6298 pAhciPortTaskState->enmTxDir == AHCITXDIR_READ 6299 ? "read" 6300 : "write", 6301 pAhciPortTaskState->uOffset, 6302 pAhciPortTaskState->cbTransfer, rcReq)); 6303 } 6304 6305 /* Finally free the task state structure because it is completely unused now. */ 6306 RTMemFree(pAhciPortTaskState); 6307 } 6308 6309 return VINF_SUCCESS; 6310 } 6311 6312 /** 6313 * Notification callback for a completed transfer. 6314 * 6315 * @returns VBox status code. 6316 * @param pInterface Pointer to the interface. 6317 * @param pvUser User data. 6318 * @param rcReq IPRT Status code of the completed request. 6319 */ 6320 static DECLCALLBACK(int) ahciTransferCompleteNotify(PPDMIBLOCKASYNCPORT pInterface, void *pvUser, int rcReq) 6321 { 6322 PAHCIPort pAhciPort = PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface); 6323 PAHCIPORTTASKSTATE pAhciPortTaskState = (PAHCIPORTTASKSTATE)pvUser; 6324 6325 ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n", 6326 __FUNCTION__, pInterface, pvUser, pAhciPortTaskState->uTag)); 6327 6328 int rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rcReq); 6329 6330 if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle) 6331 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3); 6332 return rc; 6314 6333 } 6315 6334 … … 6590 6609 case ATA_DATA_SET_MANAGEMENT: 6591 6610 { 6592 if (pAhciPort->pDrvBlock->pfnDiscard) 6611 if ( pAhciPort->pDrvBlock->pfnDiscard 6612 || ( pAhciPort->fAsyncInterface 6613 && pAhciPort->pDrvBlockAsync->pfnStartDiscard)) 6593 6614 { 6594 6615 rc = AHCITXDIR_TRIM; … … 6806 6827 if (enmTxDir != AHCITXDIR_FLUSH) 6807 6828 { 6829 bool fReadonly = true; 6808 6830 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA); 6809 6831 6810 rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, (enmTxDir == AHCITXDIR_READ) ? false : true); 6832 if ( enmTxDir == AHCITXDIR_WRITE 6833 || enmTxDir == AHCITXDIR_TRIM) 6834 fReadonly = false; 6835 6836 rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, fReadonly); 6811 6837 if (RT_FAILURE(rc)) 6812 6838 AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc)); … … 6817 6843 rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync, 6818 6844 pAhciPortTaskState); 6845 } 6846 else if (enmTxDir == AHCITXDIR_TRIM) 6847 { 6848 rc = ahciTrimRangesCreate(pAhciPort, pAhciPortTaskState); 6849 if (RT_SUCCESS(rc)) 6850 { 6851 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6852 rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->paRanges, 6853 pAhciPortTaskState->cRanges, pAhciPortTaskState); 6854 } 6819 6855 } 6820 6856 else if (enmTxDir == AHCITXDIR_READ) -
trunk/src/VBox/Devices/Storage/DrvBlock.cpp
r38622 r38878 286 286 } 287 287 288 static DECLCALLBACK(int) drvblockDiscard(PPDMIBLOCK pInterface, P PDMRANGE paRanges, unsigned cRanges)288 static DECLCALLBACK(int) drvblockDiscard(PPDMIBLOCK pInterface, PCRTRANGE paRanges, unsigned cRanges) 289 289 { 290 290 PDRVBLOCK pThis = PDMIBLOCK_2_DRVBLOCK(pInterface); … … 337 337 338 338 339 /** @copydoc PDMIBLOCKASYNC::pfnStartF Lush */339 /** @copydoc PDMIBLOCKASYNC::pfnStartFlush */ 340 340 static DECLCALLBACK(int) drvblockAsyncFlushStart(PPDMIBLOCKASYNC pInterface, void *pvUser) 341 341 { … … 359 359 360 360 return rc; 361 } 362 363 364 /** @copydoc PDMIBLOCKASYNC::pfnStartDiscard */ 365 static DECLCALLBACK(int) drvblockStartDiscard(PPDMIBLOCKASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser) 366 { 367 PDRVBLOCK pThis = PDMIBLOCKASYNC_2_DRVBLOCK(pInterface); 368 369 /* 370 * Check the state. 371 */ 372 if (!pThis->pDrvMediaAsync) 373 { 374 AssertMsgFailed(("Invalid state! Not mounted!\n")); 375 return VERR_PDM_MEDIA_NOT_MOUNTED; 376 } 377 378 return pThis->pDrvMediaAsync->pfnStartDiscard(pThis->pDrvMediaAsync, paRanges, cRanges, pvUser); 361 379 } 362 380 … … 976 994 N_("No media or async media interface below")); 977 995 996 /* Try to get the optional async interface. */ 997 pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC); 998 978 999 if (pThis->pDrvMedia->pfnDiscard) 979 1000 pThis->IBlock.pfnDiscard = drvblockDiscard; 980 1001 981 /* Try to get the optional async interface. */ 982 pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC); 1002 if ( pThis->pDrvMediaAsync 1003 && pThis->pDrvMediaAsync->pfnStartDiscard) 1004 pThis->IBlockAsync.pfnStartDiscard = drvblockStartDiscard; 983 1005 984 1006 if (RTUuidIsNull(&pThis->Uuid)) -
trunk/src/VBox/Devices/Storage/DrvDiskIntegrity.cpp
r38670 r38878 51 51 DRVDISKAIOTXDIR_WRITE, 52 52 /** Flush */ 53 DRVDISKAIOTXDIR_FLUSH 53 DRVDISKAIOTXDIR_FLUSH, 54 /** Discard */ 55 DRVDISKAIOTXDIR_DISCARD 54 56 } DRVDISKAIOTXDIR; 55 57 … … 79 81 /** I/O log entry if configured. */ 80 82 VDIOLOGENT hIoLogEntry; 83 /** Ranges to discard. */ 84 PCRTRANGE paRanges; 85 /** Number of ranges. */ 86 unsigned cRanges; 81 87 } DRVDISKAIOREQ, *PDRVDISKAIOREQ; 82 88 … … 941 947 } 942 948 949 /** @copydoc PDMIMEDIAASYNC::pfnStartDiscard */ 950 static DECLCALLBACK(int) drvdiskintStartDiscard(PPDMIMEDIA pInterface, PPDMRANGE paRanges, unsigned cRanges, void *pvUser) 951 { 952 int rc = VINF_SUCCESS; 953 VDIOLOGENT hIoLogEntry; 954 PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface); 955 PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_DISCARD, 0, NULL, 0, 0, pvUser); 956 AssertPtr(pIoReq); 957 958 pIoReq->paRanges = paRanges; 959 pIoReq->cRanges = cRanges; 960 961 if (pThis->hIoLogger) 962 { 963 rc = VDDbgIoLogStartDiscard(pThis->hIoLogger, true, (PVDRANGE)paRanges, cRanges, &hIoLogEntry); 964 AssertRC(rc); 965 } 966 967 rc = pThis->pDrvMedia->pfnStartDiscard(pThis->pDrvMedia, paRanges, cRanges, pIoReq); 968 969 if (rc == VINF_VD_ASYNC_IO_FINISHED) 970 { 971 if (pThis->hIoLogger) 972 { 973 int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL); 974 AssertRC(rc2); 975 } 976 977 RTMemFree(pIoReq); 978 } 979 else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS) 980 RTMemFree(pIoReq); 981 982 return rc; 983 } 984 943 985 /** @copydoc PDMIMEDIA::pfnFlush */ 944 986 static DECLCALLBACK(int) drvdiskintFlush(PPDMIMEDIA pInterface) … … 1069 1111 else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_WRITE) 1070 1112 rc = drvdiskintWriteRecord(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer); 1113 else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_DISCARD) 1114 rc = drvdiskintDiscardRecords(pThis, paRanges, cRanges); 1071 1115 else 1072 1116 AssertMsg(pIoReq->enmTxDir == DRVDISKAIOTXDIR_FLUSH, ("Huh?\n")); … … 1276 1320 if (pThis->pDrvMedia->pfnDiscard) 1277 1321 pThis->IMedia.pfnDiscard = drvdiskintDiscard; 1322 if ( pThis->pDrvMediaAsync 1323 && pThis->pDrvMediaAsync->pfnStartDiscard) 1324 pThis->IMediaAsync.pfnStartDiscard = drvdiskintStartDiscard; 1278 1325 1279 1326 if (pThis->fCheckConsistency) -
trunk/src/VBox/Devices/Storage/DrvSCSI.cpp
r38680 r38878 192 192 case VSCSIIOREQTXDIR_UNMAP: 193 193 { 194 P VSCSIRANGE paRanges;194 PCRTRANGE paRanges; 195 195 unsigned cRanges; 196 196 … … 199 199 200 200 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; 201 rc = pThis->pDrvBlock->pfnDiscard(pThis->pDrvBlock, (PPDMRANGE)paRanges, cRanges);201 rc = pThis->pDrvBlock->pfnDiscard(pThis->pDrvBlock, paRanges, cRanges); 202 202 pThis->pLed->Actual.s.fWriting = 0; 203 203 break; … … 234 234 if (enmTxDir == VSCSIIOREQTXDIR_READ) 235 235 pThis->pLed->Actual.s.fReading = 0; 236 else if (enmTxDir == VSCSIIOREQTXDIR_WRITE) 236 else if ( enmTxDir == VSCSIIOREQTXDIR_WRITE 237 || enmTxDir == VSCSIIOREQTXDIR_UNMAP) 237 238 pThis->pLed->Actual.s.fWriting = 0; 238 239 else … … 299 300 && pThis->cErrors++ < MAX_LOG_REL_ERRORS) 300 301 LogRel(("SCSI#%u: Flush returned rc=%Rrc\n", 302 pThis->pDrvIns->iInstance, rc)); 303 break; 304 } 305 case VSCSIIOREQTXDIR_UNMAP: 306 { 307 PCRTRANGE paRanges; 308 unsigned cRanges; 309 310 rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges); 311 AssertRC(rc); 312 313 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; 314 rc = pThis->pDrvBlockAsync->pfnStartDiscard(pThis->pDrvBlockAsync, paRanges, cRanges, hVScsiIoReq); 315 if ( RT_FAILURE(rc) 316 && rc != VERR_VD_ASYNC_IO_IN_PROGRESS 317 && pThis->cErrors++ < MAX_LOG_REL_ERRORS) 318 LogRel(("SCSI#%u: Discard returned rc=%Rrc\n", 301 319 pThis->pDrvIns->iInstance, rc)); 302 320 break; … … 396 414 *pfFeatures = 0; 397 415 398 if (pThis->pDrvBlock->pfnDiscard) 416 if ( pThis->pDrvBlock->pfnDiscard 417 || ( pThis->pDrvBlockAsync 418 && pThis->pDrvBlockAsync->pfnStartDiscard)) 399 419 *pfFeatures |= VSCSI_LUN_FEATURE_UNMAP; 400 420 … … 886 906 else 887 907 LogRel(("SCSI#%d: using async I/O\n", pDrvIns->iInstance)); 908 909 if ( pThis->pDrvBlock->pfnDiscard 910 || ( pThis->pDrvBlockAsync 911 && pThis->pDrvBlockAsync->pfnStartDiscard)) 912 LogRel(("SCSI#%d: Enabled UNMAP support\n")); 888 913 889 914 return VINF_SUCCESS; -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r38622 r38878 560 560 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 561 561 562 int rc = drvvdAsyncIOFlushSync(pvUser, pStorage); 563 if (RT_SUCCESS(rc)) 564 rc = PDMR3AsyncCompletionEpSetSize(pStorageBackend->pEndpoint, cbSize); 565 566 return rc; 562 return PDMR3AsyncCompletionEpSetSize(pStorageBackend->pEndpoint, cbSize); 567 563 } 568 564 … … 1674 1670 } 1675 1671 1676 static DECLCALLBACK(int) drvvdDiscard(PPDMIMEDIA pInterface, P PDMRANGE paRanges, unsigned cRanges)1672 static DECLCALLBACK(int) drvvdDiscard(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges) 1677 1673 { 1678 1674 LogFlowFunc(("\n")); 1679 1675 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1680 1676 1681 /** @todo: Fix the cast properly without allocating temporary memory (maybe move the type to IPRT). */ 1682 int rc = VDDiscardRanges(pThis->pDisk, (PVDRANGE)paRanges, cRanges); 1677 int rc = VDDiscardRanges(pThis->pDisk, paRanges, cRanges); 1683 1678 LogFlowFunc(("returns %Rrc\n", rc)); 1684 1679 return rc; … … 1773 1768 { 1774 1769 rc = PDMR3BlkCacheFlush(pThis->pBlkCache, pvUser); 1770 if (rc == VINF_AIO_TASK_PENDING) 1771 rc = VERR_VD_ASYNC_IO_IN_PROGRESS; 1772 else if (rc == VINF_SUCCESS) 1773 rc = VINF_VD_ASYNC_IO_FINISHED; 1774 } 1775 LogFlowFunc(("returns %Rrc\n", rc)); 1776 return rc; 1777 } 1778 1779 static DECLCALLBACK(int) drvvdStartDiscard(PPDMIMEDIAASYNC pInterface, PCRTRANGE paRanges, 1780 unsigned cRanges, void *pvUser) 1781 { 1782 int rc = VINF_SUCCESS; 1783 PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface); 1784 1785 LogFlowFunc(("paRanges=%#p cRanges=%u pvUser=%#p\n", 1786 paRanges, cRanges, pvUser)); 1787 1788 if (!pThis->pBlkCache) 1789 rc = VDAsyncDiscardRanges(pThis->pDisk, paRanges, cRanges, drvvdAsyncReqComplete, 1790 pThis, pvUser); 1791 else 1792 { 1793 rc = PDMR3BlkCacheDiscard(pThis->pBlkCache, paRanges, cRanges, pvUser); 1775 1794 if (rc == VINF_AIO_TASK_PENDING) 1776 1795 rc = VERR_VD_ASYNC_IO_IN_PROGRESS; … … 1818 1837 rc = VERR_INVALID_PARAMETER; 1819 1838 } 1839 1840 if (rc == VINF_VD_ASYNC_IO_FINISHED) 1841 PDMR3BlkCacheIoXferComplete(pThis->pBlkCache, hIoXfer, VINF_SUCCESS); 1842 else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS) 1843 PDMR3BlkCacheIoXferComplete(pThis->pBlkCache, hIoXfer, rc); 1844 1845 return VINF_SUCCESS; 1846 } 1847 1848 /** @copydoc FNPDMBLKCACHEXFERENQUEUEDISCARDDRV */ 1849 static int drvvdBlkCacheXferEnqueueDiscard(PPDMDRVINS pDrvIns, PCRTRANGE paRanges, 1850 unsigned cRanges, PPDMBLKCACHEIOXFER hIoXfer) 1851 { 1852 int rc = VINF_SUCCESS; 1853 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1854 1855 rc = VDAsyncDiscardRanges(pThis->pDisk, paRanges, cRanges, 1856 drvvdAsyncReqComplete, pThis, hIoXfer); 1820 1857 1821 1858 if (rc == VINF_VD_ASYNC_IO_FINISHED) … … 2076 2113 pThis->IMediaAsync.pfnStartWrite = drvvdStartWrite; 2077 2114 pThis->IMediaAsync.pfnStartFlush = drvvdStartFlush; 2115 pThis->IMediaAsync.pfnStartDiscard = drvvdStartDiscard; 2078 2116 2079 2117 /* Initialize supported VD interfaces. */ … … 2575 2613 2576 2614 if (!fDiscard) 2615 { 2577 2616 pThis->IMedia.pfnDiscard = NULL; 2617 pThis->IMediaAsync.pfnStartDiscard = NULL; 2618 } 2578 2619 2579 2620 if (RT_SUCCESS(rc)) … … 2666 2707 if ( fUseBlockCache 2667 2708 && !pThis->fShareable 2709 && !fDiscard 2668 2710 && RT_SUCCESS(rc)) 2669 2711 { … … 2695 2737 drvvdBlkCacheXferComplete, 2696 2738 drvvdBlkCacheXferEnqueue, 2739 drvvdBlkCacheXferEnqueueDiscard, 2697 2740 pszId); 2698 2741 if (rc == VERR_NOT_SUPPORTED) -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h
r38680 r38878 149 149 { 150 150 /** Array of ranges to unmap. */ 151 P VSCSIRANGEpaRanges;151 PRTRANGE paRanges; 152 152 /** Number of ranges. */ 153 153 unsigned cRanges; … … 335 335 */ 336 336 int vscsiIoReqUnmapEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, 337 P VSCSIRANGE paRanges, unsigned cRanges);337 PRTRANGE paRanges, unsigned cRanges); 338 338 339 339 /** -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp
r38680 r38878 88 88 89 89 int vscsiIoReqUnmapEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, 90 P VSCSIRANGE paRanges, unsigned cRanges)90 PRTRANGE paRanges, unsigned cRanges) 91 91 { 92 92 int rc = VINF_SUCCESS; … … 202 202 } 203 203 204 VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, P VSCSIRANGE *ppaRanges,204 VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PCRTRANGE *ppaRanges, 205 205 unsigned *pcRanges) 206 206 { -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
r38702 r38878 447 447 if (cBlkDesc) 448 448 { 449 P VSCSIRANGE paRanges;450 451 paRanges = (P VSCSIRANGE)RTMemAllocZ(cBlkDesc * sizeof(PVSCSIRANGE));449 PRTRANGE paRanges; 450 451 paRanges = (PRTRANGE)RTMemAllocZ(cBlkDesc * sizeof(RTRANGE)); 452 452 if (paRanges) 453 453 { -
trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp
r38847 r38878 1429 1429 PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete, 1430 1430 PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue, 1431 PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard, 1431 1432 const char *pcszId) 1432 1433 { 1433 1434 PDMDRV_ASSERT_DRVINS(pDrvIns); 1434 1435 return PDMR3BlkCacheRetainDriver(pDrvIns->Internal.s.pVMR3, pDrvIns, ppBlkCache, 1435 pfnXferComplete, pfnXferEnqueue, p cszId);1436 pfnXferComplete, pfnXferEnqueue, pfnXferEnqueueDiscard, pcszId); 1436 1437 } 1437 1438
Note:
See TracChangeset
for help on using the changeset viewer.