Implement in-order execution of non-NCQ commands.
Using status updates in r282364, block queue on BSY, DRQ or ERR bits set. This can be a performance penalization for non-NCQ commands, but it is required for proper error recovery and standard compliance. MFC after: 2 weeks
This commit is contained in:
parent
84d313761d
commit
b208a147b9
@ -140,6 +140,7 @@ struct ahci_port {
|
||||
uint8_t err_cfis[20];
|
||||
uint8_t sense_key;
|
||||
uint8_t asc;
|
||||
u_int ccs;
|
||||
uint32_t pending;
|
||||
|
||||
uint32_t clb;
|
||||
@ -204,6 +205,8 @@ struct pci_ahci_softc {
|
||||
};
|
||||
#define ahci_ctx(sc) ((sc)->asc_pi->pi_vmctx)
|
||||
|
||||
static void ahci_handle_port(struct ahci_port *p);
|
||||
|
||||
static inline void lba_to_msf(uint8_t *buf, int lba)
|
||||
{
|
||||
lba += 150;
|
||||
@ -406,6 +409,7 @@ ahci_check_stopped(struct ahci_port *p)
|
||||
*/
|
||||
if (!(p->cmd & AHCI_P_CMD_ST)) {
|
||||
if (p->pending == 0) {
|
||||
p->ccs = 0;
|
||||
p->cmd &= ~(AHCI_P_CMD_CR | AHCI_P_CMD_CCS_MASK);
|
||||
p->ci = 0;
|
||||
p->sact = 0;
|
||||
@ -783,6 +787,8 @@ ahci_handle_dsm_trim(struct ahci_port *p, int slot, uint8_t *cfis, uint32_t done
|
||||
ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
|
||||
p->pending &= ~(1 << slot);
|
||||
ahci_check_stopped(p);
|
||||
if (!first)
|
||||
ahci_handle_port(p);
|
||||
return;
|
||||
}
|
||||
goto next;
|
||||
@ -1754,20 +1760,21 @@ ahci_handle_slot(struct ahci_port *p, int slot)
|
||||
static void
|
||||
ahci_handle_port(struct ahci_port *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!(p->cmd & AHCI_P_CMD_ST))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Search for any new commands to issue ignoring those that
|
||||
* are already in-flight.
|
||||
* are already in-flight. Stop if device is busy or in error.
|
||||
*/
|
||||
for (i = 0; (i < 32) && p->ci; i++) {
|
||||
if ((p->ci & (1 << i)) && !(p->pending & (1 << i))) {
|
||||
for (; (p->ci & ~p->pending) != 0; p->ccs = ((p->ccs + 1) & 31)) {
|
||||
if ((p->tfd & (ATA_S_BUSY | ATA_S_DRQ | ATA_S_ERROR)) != 0)
|
||||
break;
|
||||
if ((p->ci & ~p->pending & (1 << p->ccs)) != 0) {
|
||||
p->cmd &= ~AHCI_P_CMD_CCS_MASK;
|
||||
p->cmd |= i << AHCI_P_CMD_CCS_SHIFT;
|
||||
ahci_handle_slot(p, i);
|
||||
p->cmd |= p->ccs << AHCI_P_CMD_CCS_SHIFT;
|
||||
ahci_handle_slot(p, p->ccs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1844,6 +1851,7 @@ ata_ioreq_cb(struct blockif_req *br, int err)
|
||||
p->pending &= ~(1 << slot);
|
||||
|
||||
ahci_check_stopped(p);
|
||||
ahci_handle_port(p);
|
||||
out:
|
||||
pthread_mutex_unlock(&sc->mtx);
|
||||
DPRINTF("%s exit\n", __func__);
|
||||
@ -1905,6 +1913,7 @@ atapi_ioreq_cb(struct blockif_req *br, int err)
|
||||
p->pending &= ~(1 << slot);
|
||||
|
||||
ahci_check_stopped(p);
|
||||
ahci_handle_port(p);
|
||||
out:
|
||||
pthread_mutex_unlock(&sc->mtx);
|
||||
DPRINTF("%s exit\n", __func__);
|
||||
|
Loading…
Reference in New Issue
Block a user