Ticket #12295: ahci_irq_storm.patch
File ahci_irq_storm.patch, 6.1 KB (added by , 9 years ago) |
---|
-
src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h
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..1a689d3 100644
a b enum { 76 76 INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt/Enable 77 77 }; 78 78 79 /* 80 * From Spec v1.3, §3.3.11 81 */ 82 typedef struct { 83 uint16 reserved:12; // Reserved 84 uint8 pmp:4; // Port Multiplier Port (PMP) : This field is not used by AHCI. 85 uint8 spm:4; // Select Power Management (SPM) : This field is not used by AHCI 86 uint8 ipm:4; // Interface Power Management Trnasitions Allowed (IPM) 87 uint8 spd:4; // Speed Allowed (SPD) 88 uint8 det:4; //Device Detection Initialization (DET) 89 } _PACKED scontrol; 90 91 #define TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED 3 92 #define NO_INITIALIZATION 0 93 #define INITIALIZATION 1 94 79 95 80 96 typedef struct { 81 97 uint32 clb; // Command List Base Address (alignment 1024 byte) … … typedef struct { 89 105 uint32 tfd; // Task File Data 90 106 uint32 sig; // Signature 91 107 uint32 ssts; // Serial ATA Status (SCR0: SStatus) 92 uint32sctl; // Serial ATA Control (SCR2: SControl)108 scontrol sctl; // Serial ATA Control (SCR2: SControl) 93 109 uint32 serr; // Serial ATA Error (SCR1: SError) **RWC** 94 110 uint32 sact; // Serial ATA Active (SCR3: SActive) **RW1** 95 111 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..d89294e 100644
a b AHCIPort::Init1() 110 110 // prdt follows after command table 111 111 112 112 // disable transitions to partial or slumber state 113 fRegs->sctl |= 0x300;113 fRegs->sctl.ipm |= TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED; /*TODO Why "|= and not "=" ??*/ 114 114 115 115 // clear IRQ status bits 116 116 fRegs->is = fRegs->is; … … AHCIPort::Init2() 156 156 TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); 157 157 TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd); 158 158 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); 160 165 TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); 161 166 TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); 162 167 TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd); … … AHCIPort::ResetDevice() 212 217 TRACE("AHCIPort::ResetDevice PORT_CMD_ST set, behaviour undefined\n"); 213 218 214 219 // perform a hard reset 215 fRegs->sctl = (fRegs->sctl & ~0xf) | 1;220 fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ? 216 221 FlushPostedWrites(); 217 222 spin(1100); 218 fRegs->sctl &= ~0xf;223 fRegs->sctl.det = NO_INITIALIZATION; 219 224 FlushPostedWrites(); 220 225 221 226 if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) { … … AHCIPort::InterruptErrorHandler(uint32 is) 364 369 TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08" 365 370 B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", fIndex, 366 371 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); 371 381 } 372 382 373 383 // read and clear SError … … AHCIPort::InterruptErrorHandler(uint32 is) 411 421 TRACE("PhyReady Change\n"); 412 422 // fResetPort = true; 413 423 } 424 //As we are in the InterruptErrorHandler, the §6.2.2.3 of the SATA specification v1.3 applies 414 425 if (is & PORT_INT_PC) { 415 426 TRACE("Port Connect Change\n"); 427 /* spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT 428 An unsolicited COMINIT is a COMINIT that is not received as a consequence of issuing a COMRESET to 429 the device (refer to Serial ATA revision 2.6). If the HBA receives an unsolicited COMINIT during normal 430 operation, the HBA shall perform the following actions; 431 - Respond to the device with a COMRESET 432 - Halt execution until PxIS.PCS is cleared to '0' by software 433 434 To detect this condition, software should check whether PxIS.PCS is set to '1' on an interrupt. The HBA 435 cannot guarantee that a device received a COMRESET because a COMINIT may appear to be solicited 436 to the HBA if it happens to occur closely to an issued COMRESET. Therefore, when software detects 437 that PxIS.PCS is set, software should first issue a COMRESET to ensure that the device receives a 438 COMRESET. Then software should perform the appropriate actions to clear PxIS.PCS to '0'. To recover, 439 software should perform error recovery actions for a fatal error condition (including restarting the 440 controller). Then software should perform a re-enumeration to check whether a new device has been inserted. 441 */ 442 /*spec v1.3 443 §3.3.5 444 Port Connect Change Status (PCS): 1=Change in Current Connect Status. 0=No 445 change in Current Connect Status. This bit reflects the state of PxSERR.DIAG.X. This 446 bit is only cleared when PxSERR.DIAG.X is cleared. 447 */ 448 /*spec v1.3 449 §3.3.12 DIAG is RWC (Read/Write '1' to clear) 450 */ 451 452 453 // perform a hard reset 454 fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ? 455 FlushPostedWrites(); 456 spin(1100); 457 fRegs->sctl.det = NO_INITIALIZATION; 458 FlushPostedWrites(); 459 460 // clear error bits to clear PxSERR.DIAG.X 461 fRegs->serr = fRegs->serr; 462 FlushPostedWrites(); 416 463 // fResetPort = true; 417 464 } 418 465 if (is & PORT_INT_UF) {