VirtualBox

Changeset 51232 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
May 12, 2014 10:14:17 AM (11 years ago)
Author:
vboxsync
Message:

AHCI: Another try to fix The AssertRelease issue during a reset. Move the second part of the port reset to the I/O thread to avoid any races. Needs minor tweaks in the BIOS driver to make it work with the changed behavior

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevAHCI.cpp

    r51114 r51232  
    10531053    AssertRC(rc);
    10541054}
     1055
     1056/**
     1057 * Finishes the port reset of the given port.
     1058 *
     1059 * @returns nothing.
     1060 * @param   pAhciPort    The port to finish the reset on.
     1061 */
     1062static void ahciPortResetFinish(PAHCIPort pAhciPort)
     1063{
     1064    /* Cancel all tasks first. */
     1065    bool fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort);
     1066    Assert(fAllTasksCanceled);
     1067
     1068    /* Signature for SATA device. */
     1069    if (pAhciPort->fATAPI)
     1070        pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
     1071    else
     1072        pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
     1073
     1074    pAhciPort->regSSTS = (0x01 << 8)  | /* Interface is active. */
     1075                         (0x03 << 0);   /* Device detected and communication established. */
     1076
     1077    /*
     1078     * Use the maximum allowed speed.
     1079     * (Not that it changes anything really)
     1080     */
     1081    switch (AHCI_PORT_SCTL_SPD_GET(pAhciPort->regSCTL))
     1082    {
     1083        case 0x01:
     1084            pAhciPort->regSSTS |= (0x01 << 4); /* Generation 1 (1.5GBps) speed. */
     1085            break;
     1086        case 0x02:
     1087        case 0x00:
     1088        default:
     1089            pAhciPort->regSSTS |= (0x02 << 4); /* Generation 2 (3.0GBps) speed. */
     1090            break;
     1091    }
     1092
     1093    /* We received a COMINIT from the device. Tell the guest. */
     1094    ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PCS);
     1095    pAhciPort->regSERR |= AHCI_PORT_SERR_X;
     1096    pAhciPort->regTFD  |= ATA_STAT_BUSY;
     1097
     1098    if ((pAhciPort->regCMD & AHCI_PORT_CMD_FRE) && (!pAhciPort->fFirstD2HFisSend))
     1099    {
     1100        ahciPostFirstD2HFisIntoMemory(pAhciPort);
     1101        ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
     1102
     1103        if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
     1104        {
     1105            int rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
     1106            AssertRC(rc);
     1107        }
     1108    }
     1109
     1110    ASMAtomicXchgBool(&pAhciPort->fPortReset, false);
     1111}
    10551112#endif
     1113
     1114/**
     1115 * Kicks the I/O thread from RC or R0.
     1116 *
     1117 * @returns nothing.
     1118 * @param   pAhci     The AHCI controller instance.
     1119 * @param   pAhciPort The port to kick.
     1120 */
     1121static void ahciIoThreadKick(PAHCI pAhci, PAHCIPort pAhciPort)
     1122{
     1123#ifdef IN_RC
     1124    PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pAhci->CTX_SUFF(pNotifierQueue));
     1125    AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n"));
     1126
     1127    if (pItem)
     1128    {
     1129        pItem->iPort = pAhciPort->iLUN;
     1130        PDMQueueInsert(pAhci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
     1131    }
     1132#else
     1133    LogFlowFunc(("Signal event semaphore\n"));
     1134    int rc = SUPSemEventSignal(pAhci->pSupDrvSession, pAhciPort->hEvtProcess);
     1135    AssertRC(rc);
     1136#endif
     1137}
    10561138
    10571139static int PortCmdIssue_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
     
    10761158        ASMAtomicOrU32(&pAhciPort->u32TasksNew, u32Value);
    10771159
    1078         /* Send a notification to R3 if u32TasksNew was before our write. */
     1160        /* Send a notification to R3 if u32TasksNew was 0 before our write. */
    10791161        if (ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
    1080         {
    1081 #ifdef IN_RC
    1082             PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(ahci->CTX_SUFF(pNotifierQueue));
    1083             AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n"));
    1084 
    1085             pItem->iPort = pAhciPort->iLUN;
    1086             PDMQueueInsert(ahci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
    1087 #else
    1088             LogFlowFunc(("Signal event semaphore\n"));
    1089             int rc = SUPSemEventSignal(ahci->pSupDrvSession, pAhciPort->hEvtProcess);
    1090             AssertRC(rc);
    1091 #endif
    1092         }
     1162            ahciIoThreadKick(ahci, pAhciPort);
    10931163    }
    10941164
     
    11791249                    pAhciPort->iLUN));
    11801250
    1181         /* Make sure the async I/O thread is not working before we start to cancel active requests. */
    1182         while (   pAhciPort->u32TasksNew
    1183                || !pAhciPort->fWrkThreadSleeping)
    1184             RTThreadYield();
    1185 
    1186         /* Cancel all tasks first. */
    1187         bool fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort);
    1188         Assert(fAllTasksCanceled);
    1189 
    11901251        pAhciPort->regSSTS = 0;
    11911252        pAhciPort->regSIG  = ~0;
    11921253        pAhciPort->regTFD  = 0x7f;
    11931254        pAhciPort->fFirstD2HFisSend = false;
     1255        pAhciPort->regSCTL = u32Value;
    11941256    }
    11951257    else if (   (u32Value & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_NINIT
     
    11971259             && pAhciPort->pDrvBase)
    11981260    {
    1199         if (pAhciPort->pDrvBase)
    1200         {
    1201             ASMAtomicXchgBool(&pAhciPort->fPortReset, false);
    1202 
    1203             /* Signature for SATA device. */
    1204             if (pAhciPort->fATAPI)
    1205                 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
    1206             else
    1207                 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
    1208 
    1209             pAhciPort->regSSTS = (0x01 << 8)  | /* Interface is active. */
    1210                                  (0x03 << 0);   /* Device detected and communication established. */
    1211 
    1212             /*
    1213              * Use the maximum allowed speed.
    1214              * (Not that it changes anything really)
    1215              */
    1216             switch (AHCI_PORT_SCTL_SPD_GET(pAhciPort->regSCTL))
    1217             {
    1218                 case 0x01:
    1219                     pAhciPort->regSSTS |= (0x01 << 4); /* Generation 1 (1.5GBps) speed. */
    1220                     break;
    1221                 case 0x02:
    1222                 case 0x00:
    1223                 default:
    1224                     pAhciPort->regSSTS |= (0x02 << 4); /* Generation 2 (3.0GBps) speed. */
    1225                     break;
    1226             }
    1227 
    1228             /* We received a COMINIT from the device. Tell the guest. */
    1229             ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PCS);
    1230             pAhciPort->regSERR |= AHCI_PORT_SERR_X;
    1231             pAhciPort->regTFD  |= ATA_STAT_BUSY;
    1232 
    1233             if ((pAhciPort->regCMD & AHCI_PORT_CMD_FRE) && (!pAhciPort->fFirstD2HFisSend))
    1234             {
    1235                 ahciPostFirstD2HFisIntoMemory(pAhciPort);
    1236                 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
    1237 
    1238                 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
    1239                 {
    1240                     int rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
    1241                     AssertRC(rc);
    1242                 }
    1243             }
    1244         }
    1245     }
    1246 
    1247     pAhciPort->regSCTL = u32Value;
     1261        pAhciPort->regSCTL = u32Value;  /* Update before kicking the I/O thread. */
     1262        pAhciPort->regSSTS = 0x1; /* Indicate device presence detected but communication not established. */
     1263
     1264        /* Kick the thread to finish the reset. */
     1265        ahciIoThreadKick(ahci, pAhciPort);
     1266    }
    12481267
    12491268    return VINF_SUCCESS;
     
    59055924    ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    59065925
    5907     if (fXchg)
     5926    if (   fXchg
     5927        && !ASMAtomicReadBool(&pAhciPort->fPortReset))
    59085928    {
    59095929        if (pAhciReq->enmTxDir == AHCITXDIR_READ)
     
    60206040         * The guest might use it for other things now because it doesn't know about that task anymore.
    60216041         */
    6022         AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_CANCELED,
     6042        AssertMsg(   pAhciReq->enmTxState == AHCITXSTATE_CANCELED
     6043                  || pAhciPort->fPortReset,
    60236044                  ("Task is not active but wasn't canceled!\n"));
    60246045
     
    67366757        } /* while tasks available */
    67376758
     6759        /* Check whether a port reset was active. */
     6760        if (   ASMAtomicReadBool(&pAhciPort->fPortReset)
     6761            && (pAhciPort->regSCTL & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_NINIT)
     6762            ahciPortResetFinish(pAhciPort);
     6763
    67386764        /*
    67396765         * Check whether a host controller reset is pending and execute the reset
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette