- Timestamp:
- Oct 7, 2016 10:49:16 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r64176 r64177 243 243 /** Flag whether the request is stored on the stack. */ 244 244 #define AHCI_REQ_IS_ON_STACK RT_BIT_32(4) 245 /** F Lag whether this request transfers data from the device to the HBA or245 /** Flag whether this request transfers data from the device to the HBA or 246 246 * the other way around .*/ 247 247 #define AHCI_REQ_XFER_2_HOST RT_BIT_32(5) … … 3583 3583 } 3584 3584 3585 /* -=-=-=-=- IMediaAsyncPort -=-=-=-=- */3586 3587 /** Makes a PAHCIPort out of a PPDMIMEDIAASYNCPORT. */3588 #define PDMIMEDIAASYNCPORT_2_PAHCIPORT(pInterface) ( (PAHCIPort)((uintptr_t)pInterface - RT_OFFSETOF(AHCIPort, IPortAsync)) )3589 3590 static void ahciWarningDiskFull(PPDMDEVINS pDevIns)3591 {3592 int rc;3593 LogRel(("AHCI: Host disk full\n"));3594 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevAHCI_DISKFULL",3595 N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));3596 AssertRC(rc);3597 }3598 3599 static void ahciWarningFileTooBig(PPDMDEVINS pDevIns)3600 {3601 int rc;3602 LogRel(("AHCI: File too big\n"));3603 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevAHCI_FILETOOBIG",3604 N_("Host system reported that the file size limit of the host file system has been exceeded. VM execution is suspended. You need to move your virtual hard disk to a filesystem which allows bigger files"));3605 AssertRC(rc);3606 }3607 3608 static void ahciWarningISCSI(PPDMDEVINS pDevIns)3609 {3610 int rc;3611 LogRel(("AHCI: iSCSI target unavailable\n"));3612 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevAHCI_ISCSIDOWN",3613 N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));3614 AssertRC(rc);3615 }3616 3617 static void ahciWarningDekMissing(PPDMDEVINS pDevIns)3618 {3619 LogRel(("AHCI#%u: DEK is missing\n", pDevIns->iInstance));3620 int rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DrvVD_DEKMISSING",3621 N_("AHCI: The DEK for this disk is missing"));3622 AssertRC(rc);3623 }3624 3625 bool ahciIsRedoSetWarning(PAHCIPort pAhciPort, int rc)3626 {3627 if (rc == VERR_DISK_FULL)3628 {3629 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))3630 ahciWarningDiskFull(pAhciPort->CTX_SUFF(pDevIns));3631 return true;3632 }3633 if (rc == VERR_FILE_TOO_BIG)3634 {3635 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))3636 ahciWarningFileTooBig(pAhciPort->CTX_SUFF(pDevIns));3637 return true;3638 }3639 if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)3640 {3641 /* iSCSI connection abort (first error) or failure to reestablish3642 * connection (second error). Pause VM. On resume we'll retry. */3643 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))3644 ahciWarningISCSI(pAhciPort->CTX_SUFF(pDevIns));3645 return true;3646 }3647 if (rc == VERR_VD_DEK_MISSING)3648 {3649 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))3650 ahciWarningDekMissing(pAhciPort->CTX_SUFF(pDevIns));3651 return true;3652 }3653 3654 return false;3655 }3656 3657 3585 /** 3658 3586 * Creates the array of ranges to trim. … … 3746 3674 3747 3675 int rc = pAhciPort->pDrvMediaEx->pfnIoReqAlloc(pAhciPort->pDrvMediaEx, &hIoReq, (void **)&pAhciReq, 3748 uTag, PDMIMEDIAEX_F_ DEFAULT);3676 uTag, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 3749 3677 if (RT_SUCCESS(rc)) 3750 3678 { … … 3785 3713 static bool ahciTransferComplete(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, int rcReq) 3786 3714 { 3787 bool fRedo = false;3788 3715 bool fCanceled = false; 3789 3716 … … 3834 3761 } 3835 3762 3836 fRedo = ahciIsRedoSetWarning(pAhciPort, rcReq); 3837 if (!fRedo) 3838 { 3839 ahciReqSetStatus(pAhciReq, ID_ERR, ATA_STAT_READY | ATA_STAT_ERR); 3840 /* 3841 * We have to duplicate the request here as the underlying I/O 3842 * request will be freed later. 3843 */ 3844 PAHCIREQ pReqDup = (PAHCIREQ)RTMemDup(pAhciReq, sizeof(AHCIREQ)); 3845 if ( pReqDup 3846 && !ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pReqDup, NULL)) 3847 RTMemFree(pReqDup); 3848 } 3849 else 3850 ASMAtomicOrU32(&pAhciPort->u32TasksRedo, RT_BIT_32(pAhciReq->uTag)); 3763 ahciReqSetStatus(pAhciReq, ID_ERR, ATA_STAT_READY | ATA_STAT_ERR); 3764 /* 3765 * We have to duplicate the request here as the underlying I/O 3766 * request will be freed later. 3767 */ 3768 PAHCIREQ pReqDup = (PAHCIREQ)RTMemDup(pAhciReq, sizeof(AHCIREQ)); 3769 if ( pReqDup 3770 && !ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pReqDup, NULL)) 3771 RTMemFree(pReqDup); 3851 3772 } 3852 3773 else … … 3905 3826 3906 3827 ahciR3ReqFree(pAhciPort, pAhciReq); 3907 if (!fRedo) 3908 { 3909 3910 /* Post a PIO setup FIS first if this is a PIO command which transfers data. */ 3911 if (fFlags & AHCI_REQ_PIO_DATA) 3912 ahciSendPioSetupFis(pAhciPort, cbTransfer, &cmdFis[0], fRead, false /* fInterrupt */); 3913 3914 if (fFlags & AHCI_REQ_CLEAR_SACT) 3915 { 3916 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ)) 3917 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(uTag)); 3918 } 3919 3920 if (fFlags & AHCI_REQ_IS_QUEUED) 3921 { 3922 /* 3923 * Always raise an interrupt after task completion; delaying 3924 * this (interrupt coalescing) increases latency and has a significant 3925 * impact on performance (see @bugref{5071}) 3926 */ 3927 ahciSendSDBFis(pAhciPort, 0, true); 3928 } 3929 else 3930 ahciSendD2HFis(pAhciPort, uTag, &cmdFis[0], true); 3931 } 3828 3829 /* Post a PIO setup FIS first if this is a PIO command which transfers data. */ 3830 if (fFlags & AHCI_REQ_PIO_DATA) 3831 ahciSendPioSetupFis(pAhciPort, cbTransfer, &cmdFis[0], fRead, false /* fInterrupt */); 3832 3833 if (fFlags & AHCI_REQ_CLEAR_SACT) 3834 { 3835 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ)) 3836 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(uTag)); 3837 } 3838 3839 if (fFlags & AHCI_REQ_IS_QUEUED) 3840 { 3841 /* 3842 * Always raise an interrupt after task completion; delaying 3843 * this (interrupt coalescing) increases latency and has a significant 3844 * impact on performance (see @bugref{5071}) 3845 */ 3846 ahciSendSDBFis(pAhciPort, 0, true); 3847 } 3848 else 3849 ahciSendD2HFis(pAhciPort, uTag, &cmdFis[0], true); 3932 3850 } 3933 3851 else … … 4065 3983 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 4066 3984 { 4067 RT_NOREF (hIoReq);3985 RT_NOREF2(hIoReq, pvIoReqAlloc); 4068 3986 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort); 4069 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc; 4070 4071 RT_NOREF3(pAhciPort, pIoReq, enmState); 4072 AssertLogRelMsgFailed(("This should not be hit because I/O requests should not be suspended\n")); 3987 3988 switch (enmState) 3989 { 3990 case PDMMEDIAEXIOREQSTATE_SUSPENDED: 3991 { 3992 /* Make sure the request is not accounted for so the VM can suspend successfully. */ 3993 uint32_t cTasksActive = ASMAtomicDecU32(&pAhciPort->cTasksActive); 3994 if (!cTasksActive && pAhciPort->pAhciR3->fSignalIdle) 3995 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3); 3996 break; 3997 } 3998 case PDMMEDIAEXIOREQSTATE_ACTIVE: 3999 /* Make sure the request is accounted for so the VM suspends only when the request is complete. */ 4000 ASMAtomicIncU32(&pAhciPort->cTasksActive); 4001 break; 4002 default: 4003 AssertMsgFailed(("Invalid request state given %u\n", enmState)); 4004 } 4073 4005 } 4074 4006
Note:
See TracChangeset
for help on using the changeset viewer.