Ticket #12295: 0001-AHCI-Fix-boot-failures-due-to-Port-Connect-Change-IR.patch

File 0001-AHCI-Fix-boot-failures-due-to-Port-Connect-Change-IR.patch, 5.1 KB (added by waddlesplash, 4 years ago)

Cleaned-up Git-patch version of Anarchos' changes.

  • src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h

    From 23963ce4ed84a440237a8416b6eb9420f5a23186 Mon Sep 17 00:00:00 2001
    From: Sylvian Kerjean <sylvain_kerjean@hotmail.com>
    Date: Sat, 8 Aug 2015 14:43:03 -0400
    Subject: [PATCH] AHCI: Fix boot failures due to "Port Connect Change" IRQ
     storm.
    
    ---
     src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h   | 15 ++++++++-
     src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp | 39 ++++++++++++++++++-----
     2 files changed, 45 insertions(+), 9 deletions(-)
    
    diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h
    index c4b0101..e9d49f1 100644
    a b enum {  
    7676    INT_DHR         = (1 << 0),     // Device to Host Register FIS Interrupt/Enable
    7777};
    7878
     79typedef struct {
     80    uint16 reserved : 12;
     81    uint8 pmp : 4;      // Port Multiplier Port: Not used by AHCI
     82    uint8 spm : 4;      // Select Power Management: Not used by AHCI
     83    uint8 ipm : 4;      // Interface Power Management Transitions Allowed
     84    uint8 spd : 4;      // Speed Allowed
     85    uint8 det : 4;      // Device Detection Initialization
     86} _PACKED scontrol;
     87
     88#define TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED 0x300
     89#define NO_INITIALIZATION 0
     90#define INITIALIZATION 1
     91
    7992
    8093typedef struct {
    8194    uint32      clb;            // Command List Base Address (alignment 1024 byte)
    typedef struct {  
    89102    uint32      tfd;            // Task File Data
    90103    uint32      sig;            // Signature
    91104    uint32      ssts;           // Serial ATA Status (SCR0: SStatus)
    92     uint32      sctl;           // Serial ATA Control (SCR2: SControl)
     105    scontrol    sctl;           // Serial ATA Control (SCR2: SControl)
    93106    uint32      serr;           // Serial ATA Error (SCR1: SError) **RWC**
    94107    uint32      sact;           // Serial ATA Active (SCR3: SActive) **RW1**
    95108    uint32      ci;             // Command Issue **RW1**
  • src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp

    diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
    index a045771..ed71461 100644
    a b AHCIPort::Init1()  
    110110    // prdt follows after command table
    111111
    112112    // disable transitions to partial or slumber state
    113     fRegs->sctl |= 0x300;
     113    fRegs->sctl.ipm |= TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED; /*TODO Why "|= and not "=" ??*/
    114114
    115115    // clear IRQ status bits
    116116    fRegs->is = fRegs->is;
    AHCIPort::Init2()  
    156156    TRACE("is   0x%08" B_PRIx32 "\n", fRegs->is);
    157157    TRACE("cmd  0x%08" B_PRIx32 "\n", fRegs->cmd);
    158158    TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts);
    159     TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl);
     159    TRACE("sctl.reserved 0x%04" B_PRIx16 "\n", fRegs->sctl.reserved);
     160    TRACE("sctl.pmp 0x%02" B_PRIx8 "\n", fRegs->sctl.pmp);
     161    TRACE("sctl.spm 0x%02" B_PRIx8 "\n", fRegs->sctl.spm);
     162    TRACE("sctl.ipm 0x%02" B_PRIx8 "\n", fRegs->sctl.ipm);
     163    TRACE("sctl.spd 0x%02" B_PRIx8 "\n", fRegs->sctl.spd);
     164    TRACE("sctl.det 0x%02" B_PRIx8 "\n", fRegs->sctl.det);
    160165    TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr);
    161166    TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact);
    162167    TRACE("tfd  0x%08" B_PRIx32 "\n", fRegs->tfd);
    AHCIPort::ResetDevice()  
    212217        TRACE("AHCIPort::ResetDevice PORT_CMD_ST set, behaviour undefined\n");
    213218
    214219    // perform a hard reset
    215     fRegs->sctl = (fRegs->sctl & ~0xf) | 1;
     220    fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ?
    216221    FlushPostedWrites();
    217222    spin(1100);
    218     fRegs->sctl &= ~0xf;
     223    fRegs->sctl.det = NO_INITIALIZATION;
    219224    FlushPostedWrites();
    220225
    221226    if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) {
    AHCIPort::InterruptErrorHandler(uint32 is)  
    364369        TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08"
    365370            B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", fIndex,
    366371            fCommandsActive, is, ci);
    367 
    368         TRACE("ssts 0x%08" B_PRIx32 ", sctl 0x%08" B_PRIx32 ", serr 0x%08"
    369             B_PRIx32 ", sact 0x%08" B_PRIx32 "\n",
    370             fRegs->ssts, fRegs->sctl, fRegs->serr, fRegs->sact);
     372        TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts);
     373        TRACE("sctl.reserved 0x%04" B_PRIx16 "\n", fRegs->sctl.reserved);
     374        TRACE("sctl.pmp 0x%02" B_PRIx8 "\n", fRegs->sctl.pmp);
     375        TRACE("sctl.spm 0x%02" B_PRIx8 "\n", fRegs->sctl.spm);
     376        TRACE("sctl.ipm 0x%02" B_PRIx8 "\n", fRegs->sctl.ipm);
     377        TRACE("sctl.spd 0x%02" B_PRIx8 "\n", fRegs->sctl.spd);
     378        TRACE("sctl.det 0x%02" B_PRIx8 "\n", fRegs->sctl.det);
     379        TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr);
     380        TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact);
    371381    }
    372382
    373383    // read and clear SError
    AHCIPort::InterruptErrorHandler(uint32 is)  
    413423    }
    414424    if (is & PORT_INT_PC) {
    415425        TRACE("Port Connect Change\n");
     426        /* spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT (a COMINIT that is
     427         * not received as a consequence of issuing a COMRESET to the device) */
     428
     429        // perform a hard reset
     430        fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ?
     431        FlushPostedWrites();
     432        spin(1100); // specification says you must wait 1ms
     433        fRegs->sctl.det = NO_INITIALIZATION;
     434        FlushPostedWrites();
     435
     436        // clear error bits to clear PxSERR.DIAG.X
     437        fRegs->serr = fRegs->serr;
     438        FlushPostedWrites();
    416439//      fResetPort = true;
    417440    }
    418441    if (is & PORT_INT_UF) {