AHCI - Better reset sequencing, bug fixes
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 9 Jun 2009 18:47:54 +0000 (11:47 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 9 Jun 2009 18:47:54 +0000 (11:47 -0700)
commitcf5f3a81b0df75cd4844c3c89f008e209d59b218
tree59d080991c1ad8b541f91f1b9e38a2a6a5fdc1fd
parentb089d0bfa66d195e24630869579f0cbc1a48e459
AHCI - Better reset sequencing, bug fixes

* Change the reset sequence.  If the first hardreset fails do a second
  hardreset.  If that fails then try doing a softreset.  This seems to
  catch all the cases.  It is unclear why the reset sequence fails at
  random points but it seems to be a combination of the port command
  processor state and the device state.  COMRESET does not actually reset
  everything like its supposed to.

* Temporarily set ap_state to AP_S_NORMAL when starting a reset
  sequence so commands do not just fail due to a previously failed
  condition on the port.

* Restoration of command register state now depends on whether the
  reset succeeded or failed.

* Note that only SERR_DIAG_X needs to be cleared to allow for the
  next TFD update.  These updates are serialized by the controller
  and there may be more then one.  Add a function ahci_flush_tfd() which
  flushes all of them.

* Add ahci_port_hardstop() for dealing with failed ports and device
  removals, instead of using ahci_port_hardreset().  This function
  tries to do multiple transitions via section 10.10.1.  These
  transitions are not well documented by the standard.

* Fix ahci_poll() to not queue a command if the port is in a failed
  state, as this really messes up our port processing state machine.
sys/dev/disk/ahci/ahci.c