Bunch of microoptimizations to reduce dereferences and cache collisions.

This commit is contained in:
mav 2014-09-08 12:11:49 +00:00
parent 7105bcbd70
commit 07b6763268
3 changed files with 137 additions and 163 deletions

View File

@ -61,31 +61,31 @@ static void ahci_ch_pm(void *arg);
static void ahci_ch_intr(void *arg); static void ahci_ch_intr(void *arg);
static void ahci_ch_intr_direct(void *arg); static void ahci_ch_intr_direct(void *arg);
static void ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus); static void ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus);
static void ahci_begin_transaction(device_t dev, union ccb *ccb); static void ahci_begin_transaction(struct ahci_channel *ch, union ccb *ccb);
static void ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error); static void ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
static void ahci_execute_transaction(struct ahci_slot *slot); static void ahci_execute_transaction(struct ahci_slot *slot);
static void ahci_timeout(struct ahci_slot *slot); static void ahci_timeout(struct ahci_slot *slot);
static void ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et); static void ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et);
static int ahci_setup_fis(device_t dev, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag); static int ahci_setup_fis(struct ahci_channel *ch, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag);
static void ahci_dmainit(device_t dev); static void ahci_dmainit(device_t dev);
static void ahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); static void ahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
static void ahci_dmafini(device_t dev); static void ahci_dmafini(device_t dev);
static void ahci_slotsalloc(device_t dev); static void ahci_slotsalloc(device_t dev);
static void ahci_slotsfree(device_t dev); static void ahci_slotsfree(device_t dev);
static void ahci_reset(device_t dev); static void ahci_reset(struct ahci_channel *ch);
static void ahci_start(device_t dev, int fbs); static void ahci_start(struct ahci_channel *ch, int fbs);
static void ahci_stop(device_t dev); static void ahci_stop(struct ahci_channel *ch);
static void ahci_clo(device_t dev); static void ahci_clo(struct ahci_channel *ch);
static void ahci_start_fr(device_t dev); static void ahci_start_fr(struct ahci_channel *ch);
static void ahci_stop_fr(device_t dev); static void ahci_stop_fr(struct ahci_channel *ch);
static int ahci_sata_connect(struct ahci_channel *ch); static int ahci_sata_connect(struct ahci_channel *ch);
static int ahci_sata_phy_reset(device_t dev); static int ahci_sata_phy_reset(struct ahci_channel *ch);
static int ahci_wait_ready(device_t dev, int t, int t0); static int ahci_wait_ready(struct ahci_channel *ch, int t, int t0);
static void ahci_issue_recovery(device_t dev); static void ahci_issue_recovery(struct ahci_channel *ch);
static void ahci_process_read_log(device_t dev, union ccb *ccb); static void ahci_process_read_log(struct ahci_channel *ch, union ccb *ccb);
static void ahci_process_request_sense(device_t dev, union ccb *ccb); static void ahci_process_request_sense(struct ahci_channel *ch, union ccb *ccb);
static void ahciaction(struct cam_sim *sim, union ccb *ccb); static void ahciaction(struct cam_sim *sim, union ccb *ccb);
static void ahcipoll(struct cam_sim *sim); static void ahcipoll(struct cam_sim *sim);
@ -669,7 +669,7 @@ ahci_ch_attach(device_t dev)
} }
if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL, if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL,
ctlr->direct ? ahci_ch_intr_direct : ahci_ch_intr, ctlr->direct ? ahci_ch_intr_direct : ahci_ch_intr,
dev, &ch->ih))) { ch, &ch->ih))) {
device_printf(dev, "Unable to setup interrupt\n"); device_printf(dev, "Unable to setup interrupt\n");
error = ENXIO; error = ENXIO;
goto err1; goto err1;
@ -698,7 +698,7 @@ ahci_ch_attach(device_t dev)
} }
/* Construct SIM entry */ /* Construct SIM entry */
ch->sim = cam_sim_alloc(ahciaction, ahcipoll, "ahcich", ch, ch->sim = cam_sim_alloc(ahciaction, ahcipoll, "ahcich", ch,
device_get_unit(dev), &ch->mtx, device_get_unit(dev), (struct mtx *)&ch->mtx,
min(2, ch->numslots), min(2, ch->numslots),
(ch->caps & AHCI_CAP_SNCQ) ? ch->numslots : 0, (ch->caps & AHCI_CAP_SNCQ) ? ch->numslots : 0,
devq); devq);
@ -722,7 +722,7 @@ ahci_ch_attach(device_t dev)
if (ch->pm_level > 3) { if (ch->pm_level > 3) {
callout_reset(&ch->pm_timer, callout_reset(&ch->pm_timer,
(ch->pm_level == 4) ? hz / 1000 : hz / 8, (ch->pm_level == 4) ? hz / 1000 : hz / 8,
ahci_ch_pm, dev); ahci_ch_pm, ch);
} }
mtx_unlock(&ch->mtx); mtx_unlock(&ch->mtx);
return (0); return (0);
@ -792,8 +792,8 @@ ahci_ch_init(device_t dev)
(AHCI_P_CMD_ACTIVE | AHCI_P_CMD_POD | AHCI_P_CMD_SUD | (AHCI_P_CMD_ACTIVE | AHCI_P_CMD_POD | AHCI_P_CMD_SUD |
((ch->pm_level == 2 || ch->pm_level == 3) ? AHCI_P_CMD_ALPE : 0) | ((ch->pm_level == 2 || ch->pm_level == 3) ? AHCI_P_CMD_ALPE : 0) |
((ch->pm_level > 2) ? AHCI_P_CMD_ASP : 0 ))); ((ch->pm_level > 2) ? AHCI_P_CMD_ASP : 0 )));
ahci_start_fr(dev); ahci_start_fr(ch);
ahci_start(dev, 1); ahci_start(ch, 1);
return (0); return (0);
} }
@ -805,8 +805,8 @@ ahci_ch_deinit(device_t dev)
/* Disable port interrupts. */ /* Disable port interrupts. */
ATA_OUTL(ch->r_mem, AHCI_P_IE, 0); ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
/* Reset command register. */ /* Reset command register. */
ahci_stop(dev); ahci_stop(ch);
ahci_stop_fr(dev); ahci_stop_fr(ch);
ATA_OUTL(ch->r_mem, AHCI_P_CMD, 0); ATA_OUTL(ch->r_mem, AHCI_P_CMD, 0);
/* Allow everything, including partial and slumber modes. */ /* Allow everything, including partial and slumber modes. */
ATA_OUTL(ch->r_mem, AHCI_P_SCTL, 0); ATA_OUTL(ch->r_mem, AHCI_P_SCTL, 0);
@ -845,7 +845,7 @@ ahci_ch_resume(device_t dev)
mtx_lock(&ch->mtx); mtx_lock(&ch->mtx);
ahci_ch_init(dev); ahci_ch_init(dev);
ahci_reset(dev); ahci_reset(ch);
xpt_release_simq(ch->sim, TRUE); xpt_release_simq(ch->sim, TRUE);
mtx_unlock(&ch->mtx); mtx_unlock(&ch->mtx);
return (0); return (0);
@ -976,7 +976,7 @@ ahci_slotsalloc(device_t dev)
for (i = 0; i < ch->numslots; i++) { for (i = 0; i < ch->numslots; i++) {
struct ahci_slot *slot = &ch->slot[i]; struct ahci_slot *slot = &ch->slot[i];
slot->dev = dev; slot->ch = ch;
slot->slot = i; slot->slot = i;
slot->state = AHCI_SLOT_EMPTY; slot->state = AHCI_SLOT_EMPTY;
slot->ccb = NULL; slot->ccb = NULL;
@ -1006,9 +1006,8 @@ ahci_slotsfree(device_t dev)
} }
static int static int
ahci_phy_check_events(device_t dev, u_int32_t serr) ahci_phy_check_events(struct ahci_channel *ch, u_int32_t serr)
{ {
struct ahci_channel *ch = device_get_softc(dev);
if (((ch->pm_level == 0) && (serr & ATA_SE_PHY_CHANGED)) || if (((ch->pm_level == 0) && (serr & ATA_SE_PHY_CHANGED)) ||
((ch->pm_level != 0 || ch->listening) && (serr & ATA_SE_EXCHANGED))) { ((ch->pm_level != 0 || ch->listening) && (serr & ATA_SE_EXCHANGED))) {
@ -1017,11 +1016,11 @@ ahci_phy_check_events(device_t dev, u_int32_t serr)
if (bootverbose) { if (bootverbose) {
if ((status & ATA_SS_DET_MASK) != ATA_SS_DET_NO_DEVICE) if ((status & ATA_SS_DET_MASK) != ATA_SS_DET_NO_DEVICE)
device_printf(dev, "CONNECT requested\n"); device_printf(ch->dev, "CONNECT requested\n");
else else
device_printf(dev, "DISCONNECT requested\n"); device_printf(ch->dev, "DISCONNECT requested\n");
} }
ahci_reset(dev); ahci_reset(ch);
if ((ccb = xpt_alloc_ccb_nowait()) == NULL) if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
return (0); return (0);
if (xpt_create_path(&ccb->ccb_h.path, NULL, if (xpt_create_path(&ccb->ccb_h.path, NULL,
@ -1037,11 +1036,11 @@ ahci_phy_check_events(device_t dev, u_int32_t serr)
} }
static void static void
ahci_cpd_check_events(device_t dev) ahci_cpd_check_events(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
u_int32_t status; u_int32_t status;
union ccb *ccb; union ccb *ccb;
device_t dev;
if (ch->pm_level == 0) if (ch->pm_level == 0)
return; return;
@ -1051,12 +1050,13 @@ ahci_cpd_check_events(device_t dev)
return; return;
if (bootverbose) { if (bootverbose) {
dev = ch->dev;
if (status & AHCI_P_CMD_CPS) { if (status & AHCI_P_CMD_CPS) {
device_printf(dev, "COLD CONNECT requested\n"); device_printf(dev, "COLD CONNECT requested\n");
} else } else
device_printf(dev, "COLD DISCONNECT requested\n"); device_printf(dev, "COLD DISCONNECT requested\n");
} }
ahci_reset(dev); ahci_reset(ch);
if ((ccb = xpt_alloc_ccb_nowait()) == NULL) if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
return; return;
if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(ch->sim), if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(ch->sim),
@ -1068,16 +1068,15 @@ ahci_cpd_check_events(device_t dev)
} }
static void static void
ahci_notify_events(device_t dev, u_int32_t status) ahci_notify_events(struct ahci_channel *ch, u_int32_t status)
{ {
struct ahci_channel *ch = device_get_softc(dev);
struct cam_path *dpath; struct cam_path *dpath;
int i; int i;
if (ch->caps & AHCI_CAP_SSNTF) if (ch->caps & AHCI_CAP_SSNTF)
ATA_OUTL(ch->r_mem, AHCI_P_SNTF, status); ATA_OUTL(ch->r_mem, AHCI_P_SNTF, status);
if (bootverbose) if (bootverbose)
device_printf(dev, "SNTF 0x%04x\n", status); device_printf(ch->dev, "SNTF 0x%04x\n", status);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if ((status & (1 << i)) == 0) if ((status & (1 << i)) == 0)
continue; continue;
@ -1106,8 +1105,7 @@ ahci_done(struct ahci_channel *ch, union ccb *ccb)
static void static void
ahci_ch_intr(void *arg) ahci_ch_intr(void *arg)
{ {
device_t dev = (device_t)arg; struct ahci_channel *ch = (struct ahci_channel *)arg;
struct ahci_channel *ch = device_get_softc(dev);
uint32_t istatus; uint32_t istatus;
/* Read interrupt statuses. */ /* Read interrupt statuses. */
@ -1123,8 +1121,7 @@ ahci_ch_intr(void *arg)
static void static void
ahci_ch_intr_direct(void *arg) ahci_ch_intr_direct(void *arg)
{ {
device_t dev = (device_t)arg; struct ahci_channel *ch = (struct ahci_channel *)arg;
struct ahci_channel *ch = device_get_softc(dev);
struct ccb_hdr *ccb_h; struct ccb_hdr *ccb_h;
uint32_t istatus; uint32_t istatus;
@ -1147,8 +1144,7 @@ ahci_ch_intr_direct(void *arg)
static void static void
ahci_ch_pm(void *arg) ahci_ch_pm(void *arg)
{ {
device_t dev = (device_t)arg; struct ahci_channel *ch = (struct ahci_channel *)arg;
struct ahci_channel *ch = device_get_softc(dev);
uint32_t work; uint32_t work;
if (ch->numrslots != 0) if (ch->numrslots != 0)
@ -1164,7 +1160,6 @@ ahci_ch_pm(void *arg)
static void static void
ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus) ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus)
{ {
device_t dev = ch->dev;
uint32_t cstatus, serr = 0, sntf = 0, ok, err; uint32_t cstatus, serr = 0, sntf = 0, ok, err;
enum ahci_err_type et; enum ahci_err_type et;
int i, ccs, port, reset = 0; int i, ccs, port, reset = 0;
@ -1206,12 +1201,12 @@ ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus)
serr = ATA_INL(ch->r_mem, AHCI_P_SERR); serr = ATA_INL(ch->r_mem, AHCI_P_SERR);
if (serr) { if (serr) {
ATA_OUTL(ch->r_mem, AHCI_P_SERR, serr); ATA_OUTL(ch->r_mem, AHCI_P_SERR, serr);
reset = ahci_phy_check_events(dev, serr); reset = ahci_phy_check_events(ch, serr);
} }
} }
/* Process cold presence detection events */ /* Process cold presence detection events */
if ((istatus & AHCI_P_IX_CPD) && !reset) if ((istatus & AHCI_P_IX_CPD) && !reset)
ahci_cpd_check_events(dev); ahci_cpd_check_events(ch);
/* Process command errors */ /* Process command errors */
if (istatus & (AHCI_P_IX_OF | AHCI_P_IX_IF | if (istatus & (AHCI_P_IX_OF | AHCI_P_IX_IF |
AHCI_P_IX_HBD | AHCI_P_IX_HBF | AHCI_P_IX_TFE)) { AHCI_P_IX_HBD | AHCI_P_IX_HBF | AHCI_P_IX_TFE)) {
@ -1306,14 +1301,13 @@ ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus)
} }
/* Process NOTIFY events */ /* Process NOTIFY events */
if (sntf) if (sntf)
ahci_notify_events(dev, sntf); ahci_notify_events(ch, sntf);
} }
/* Must be called with channel locked. */ /* Must be called with channel locked. */
static int static int
ahci_check_collision(device_t dev, union ccb *ccb) ahci_check_collision(struct ahci_channel *ch, union ccb *ccb)
{ {
struct ahci_channel *ch = device_get_softc(dev);
int t = ccb->ccb_h.target_id; int t = ccb->ccb_h.target_id;
if ((ccb->ccb_h.func_code == XPT_ATA_IO) && if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
@ -1362,9 +1356,8 @@ ahci_check_collision(device_t dev, union ccb *ccb)
/* Must be called with channel locked. */ /* Must be called with channel locked. */
static void static void
ahci_begin_transaction(device_t dev, union ccb *ccb) ahci_begin_transaction(struct ahci_channel *ch, union ccb *ccb)
{ {
struct ahci_channel *ch = device_get_softc(dev);
struct ahci_slot *slot; struct ahci_slot *slot;
int tag, tags; int tag, tags;
@ -1373,14 +1366,14 @@ ahci_begin_transaction(device_t dev, union ccb *ccb)
if ((ccb->ccb_h.func_code == XPT_ATA_IO) && if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA))
tags = ch->curr[ccb->ccb_h.target_id].tags; tags = ch->curr[ccb->ccb_h.target_id].tags;
tag = ch->lastslot; if (ch->lastslot + 1 < tags)
while (1) { tag = ffs(~(ch->oslots >> (ch->lastslot + 1)));
if (tag >= tags) else
tag = 0; tag = 0;
if (ch->slot[tag].state == AHCI_SLOT_EMPTY) if (tag == 0 || tag + ch->lastslot >= tags)
break; tag = ffs(~ch->oslots) - 1;
tag++; else
}; tag += ch->lastslot;
ch->lastslot = tag; ch->lastslot = tag;
/* Occupy chosen slot. */ /* Occupy chosen slot. */
slot = &ch->slot[tag]; slot = &ch->slot[tag];
@ -1389,7 +1382,7 @@ ahci_begin_transaction(device_t dev, union ccb *ccb)
if (ch->numrslots == 0 && ch->pm_level > 3) if (ch->numrslots == 0 && ch->pm_level > 3)
callout_stop(&ch->pm_timer); callout_stop(&ch->pm_timer);
/* Update channel stats. */ /* Update channel stats. */
ch->oslots |= (1 << slot->slot); ch->oslots |= (1 << tag);
ch->numrslots++; ch->numrslots++;
ch->numrslotspd[ccb->ccb_h.target_id]++; ch->numrslotspd[ccb->ccb_h.target_id]++;
if ((ccb->ccb_h.func_code == XPT_ATA_IO) && if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
@ -1400,14 +1393,15 @@ ahci_begin_transaction(device_t dev, union ccb *ccb)
} }
if ((ccb->ccb_h.func_code == XPT_ATA_IO) && if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT))) (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)))
ch->aslots |= (1 << slot->slot); ch->aslots |= (1 << tag);
slot->dma.nsegs = 0;
if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
slot->state = AHCI_SLOT_LOADING; slot->state = AHCI_SLOT_LOADING;
bus_dmamap_load_ccb(ch->dma.data_tag, slot->dma.data_map, ccb, bus_dmamap_load_ccb(ch->dma.data_tag, slot->dma.data_map, ccb,
ahci_dmasetprd, slot, 0); ahci_dmasetprd, slot, 0);
} else } else {
slot->dma.nsegs = 0;
ahci_execute_transaction(slot); ahci_execute_transaction(slot);
}
} }
/* Locked by busdma engine. */ /* Locked by busdma engine. */
@ -1415,13 +1409,13 @@ static void
ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error) ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{ {
struct ahci_slot *slot = arg; struct ahci_slot *slot = arg;
struct ahci_channel *ch = device_get_softc(slot->dev); struct ahci_channel *ch = slot->ch;
struct ahci_cmd_tab *ctp; struct ahci_cmd_tab *ctp;
struct ahci_dma_prd *prd; struct ahci_dma_prd *prd;
int i; int i;
if (error) { if (error) {
device_printf(slot->dev, "DMA load error\n"); device_printf(ch->dev, "DMA load error\n");
ahci_end_transaction(slot, AHCI_ERR_INVALID); ahci_end_transaction(slot, AHCI_ERR_INVALID);
return; return;
} }
@ -1446,8 +1440,7 @@ ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
static void static void
ahci_execute_transaction(struct ahci_slot *slot) ahci_execute_transaction(struct ahci_slot *slot)
{ {
device_t dev = slot->dev; struct ahci_channel *ch = slot->ch;
struct ahci_channel *ch = device_get_softc(dev);
struct ahci_cmd_tab *ctp; struct ahci_cmd_tab *ctp;
struct ahci_cmd_list *clp; struct ahci_cmd_list *clp;
union ccb *ccb = slot->ccb; union ccb *ccb = slot->ccb;
@ -1460,7 +1453,7 @@ ahci_execute_transaction(struct ahci_slot *slot)
ctp = (struct ahci_cmd_tab *) ctp = (struct ahci_cmd_tab *)
(ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot)); (ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot));
/* Setup the FIS for this request */ /* Setup the FIS for this request */
if (!(fis_size = ahci_setup_fis(dev, ctp, ccb, slot->slot))) { if (!(fis_size = ahci_setup_fis(ch, ctp, ccb, slot->slot))) {
device_printf(ch->dev, "Setting up SATA FIS failed\n"); device_printf(ch->dev, "Setting up SATA FIS failed\n");
ahci_end_transaction(slot, AHCI_ERR_INVALID); ahci_end_transaction(slot, AHCI_ERR_INVALID);
return; return;
@ -1481,9 +1474,9 @@ ahci_execute_transaction(struct ahci_slot *slot)
if (ccb->ataio.cmd.control & ATA_A_RESET) { if (ccb->ataio.cmd.control & ATA_A_RESET) {
softreset = 1; softreset = 1;
/* Kick controller into sane state */ /* Kick controller into sane state */
ahci_stop(dev); ahci_stop(ch);
ahci_clo(dev); ahci_clo(ch);
ahci_start(dev, 0); ahci_start(ch, 0);
clp->cmd_flags |= AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY; clp->cmd_flags |= AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY;
} else { } else {
softreset = 2; softreset = 2;
@ -1561,9 +1554,9 @@ ahci_execute_transaction(struct ahci_slot *slot)
} }
if (timeout && (count >= timeout)) { if (timeout && (count >= timeout)) {
device_printf(dev, "Poll timeout on slot %d port %d\n", device_printf(ch->dev, "Poll timeout on slot %d port %d\n",
slot->slot, port); slot->slot, port);
device_printf(dev, "is %08x cs %08x ss %08x " device_printf(ch->dev, "is %08x cs %08x ss %08x "
"rs %08x tfd %02x serr %08x cmd %08x\n", "rs %08x tfd %02x serr %08x cmd %08x\n",
ATA_INL(ch->r_mem, AHCI_P_IS), ATA_INL(ch->r_mem, AHCI_P_IS),
ATA_INL(ch->r_mem, AHCI_P_CI), ATA_INL(ch->r_mem, AHCI_P_CI),
@ -1588,9 +1581,8 @@ ahci_execute_transaction(struct ahci_slot *slot)
/* Must be called with channel locked. */ /* Must be called with channel locked. */
static void static void
ahci_process_timeout(device_t dev) ahci_process_timeout(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
int i; int i;
mtx_assert(&ch->mtx, MA_OWNED); mtx_assert(&ch->mtx, MA_OWNED);
@ -1605,9 +1597,8 @@ ahci_process_timeout(device_t dev)
/* Must be called with channel locked. */ /* Must be called with channel locked. */
static void static void
ahci_rearm_timeout(device_t dev) ahci_rearm_timeout(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
int i; int i;
mtx_assert(&ch->mtx, MA_OWNED); mtx_assert(&ch->mtx, MA_OWNED);
@ -1629,8 +1620,8 @@ ahci_rearm_timeout(device_t dev)
static void static void
ahci_timeout(struct ahci_slot *slot) ahci_timeout(struct ahci_slot *slot)
{ {
device_t dev = slot->dev; struct ahci_channel *ch = slot->ch;
struct ahci_channel *ch = device_get_softc(dev); device_t dev = ch->dev;
uint32_t sstatus; uint32_t sstatus;
int ccs; int ccs;
int i; int i;
@ -1697,7 +1688,7 @@ ahci_timeout(struct ahci_slot *slot)
xpt_freeze_simq(ch->sim, 1); xpt_freeze_simq(ch->sim, 1);
ch->toslots |= (1 << slot->slot); ch->toslots |= (1 << slot->slot);
if ((ch->rslots & ~ch->toslots) == 0) if ((ch->rslots & ~ch->toslots) == 0)
ahci_process_timeout(dev); ahci_process_timeout(ch);
else else
device_printf(dev, " ... waiting for slots %08x\n", device_printf(dev, " ... waiting for slots %08x\n",
ch->rslots & ~ch->toslots); ch->rslots & ~ch->toslots);
@ -1708,8 +1699,7 @@ ahci_timeout(struct ahci_slot *slot)
static void static void
ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et) ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
{ {
device_t dev = slot->dev; struct ahci_channel *ch = slot->ch;
struct ahci_channel *ch = device_get_softc(dev);
union ccb *ccb = slot->ccb; union ccb *ccb = slot->ccb;
struct ahci_cmd_list *clp; struct ahci_cmd_list *clp;
int lastto; int lastto;
@ -1867,15 +1857,15 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
(ccb->ataio.cmd.control & ATA_A_RESET) && (ccb->ataio.cmd.control & ATA_A_RESET) &&
et == AHCI_ERR_NONE) { et == AHCI_ERR_NONE) {
ccb->ataio.cmd.control &= ~ATA_A_RESET; ccb->ataio.cmd.control &= ~ATA_A_RESET;
ahci_begin_transaction(dev, ccb); ahci_begin_transaction(ch, ccb);
return; return;
} }
/* If it was our READ LOG command - process it. */ /* If it was our READ LOG command - process it. */
if (ccb->ccb_h.recovery_type == RECOVERY_READ_LOG) { if (ccb->ccb_h.recovery_type == RECOVERY_READ_LOG) {
ahci_process_read_log(dev, ccb); ahci_process_read_log(ch, ccb);
/* If it was our REQUEST SENSE command - process it. */ /* If it was our REQUEST SENSE command - process it. */
} else if (ccb->ccb_h.recovery_type == RECOVERY_REQUEST_SENSE) { } else if (ccb->ccb_h.recovery_type == RECOVERY_REQUEST_SENSE) {
ahci_process_request_sense(dev, ccb); ahci_process_request_sense(ch, ccb);
/* If it was NCQ or ATAPI command error, put result on hold. */ /* If it was NCQ or ATAPI command error, put result on hold. */
} else if (et == AHCI_ERR_NCQ || } else if (et == AHCI_ERR_NCQ ||
((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR && ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR &&
@ -1888,27 +1878,27 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
if (ch->rslots == 0) { if (ch->rslots == 0) {
/* if there was fatal error - reset port. */ /* if there was fatal error - reset port. */
if (ch->toslots != 0 || ch->fatalerr) { if (ch->toslots != 0 || ch->fatalerr) {
ahci_reset(dev); ahci_reset(ch);
} else { } else {
/* if we have slots in error, we can reinit port. */ /* if we have slots in error, we can reinit port. */
if (ch->eslots != 0) { if (ch->eslots != 0) {
ahci_stop(dev); ahci_stop(ch);
ahci_clo(dev); ahci_clo(ch);
ahci_start(dev, 1); ahci_start(ch, 1);
} }
/* if there commands on hold, we can do READ LOG. */ /* if there commands on hold, we can do READ LOG. */
if (!ch->recoverycmd && ch->numhslots) if (!ch->recoverycmd && ch->numhslots)
ahci_issue_recovery(dev); ahci_issue_recovery(ch);
} }
/* If all the rest of commands are in timeout - give them chance. */ /* If all the rest of commands are in timeout - give them chance. */
} else if ((ch->rslots & ~ch->toslots) == 0 && } else if ((ch->rslots & ~ch->toslots) == 0 &&
et != AHCI_ERR_TIMEOUT) et != AHCI_ERR_TIMEOUT)
ahci_rearm_timeout(dev); ahci_rearm_timeout(ch);
/* Unfreeze frozen command. */ /* Unfreeze frozen command. */
if (ch->frozen && !ahci_check_collision(dev, ch->frozen)) { if (ch->frozen && !ahci_check_collision(ch, ch->frozen)) {
union ccb *fccb = ch->frozen; union ccb *fccb = ch->frozen;
ch->frozen = NULL; ch->frozen = NULL;
ahci_begin_transaction(dev, fccb); ahci_begin_transaction(ch, fccb);
xpt_release_simq(ch->sim, TRUE); xpt_release_simq(ch->sim, TRUE);
} }
/* Start PM timer. */ /* Start PM timer. */
@ -1920,9 +1910,8 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
} }
static void static void
ahci_issue_recovery(device_t dev) ahci_issue_recovery(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
union ccb *ccb; union ccb *ccb;
struct ccb_ataio *ataio; struct ccb_ataio *ataio;
struct ccb_scsiio *csio; struct ccb_scsiio *csio;
@ -1935,7 +1924,7 @@ ahci_issue_recovery(device_t dev)
} }
ccb = xpt_alloc_ccb_nowait(); ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) { if (ccb == NULL) {
device_printf(dev, "Unable to allocate recovery command\n"); device_printf(ch->dev, "Unable to allocate recovery command\n");
completeall: completeall:
/* We can't do anything -- complete held commands. */ /* We can't do anything -- complete held commands. */
for (i = 0; i < ch->numslots; i++) { for (i = 0; i < ch->numslots; i++) {
@ -1947,7 +1936,7 @@ ahci_issue_recovery(device_t dev)
ch->hold[i] = NULL; ch->hold[i] = NULL;
ch->numhslots--; ch->numhslots--;
} }
ahci_reset(dev); ahci_reset(ch);
return; return;
} }
ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */ ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */
@ -1961,7 +1950,7 @@ ahci_issue_recovery(device_t dev)
ataio->data_ptr = malloc(512, M_AHCI, M_NOWAIT); ataio->data_ptr = malloc(512, M_AHCI, M_NOWAIT);
if (ataio->data_ptr == NULL) { if (ataio->data_ptr == NULL) {
xpt_free_ccb(ccb); xpt_free_ccb(ccb);
device_printf(dev, device_printf(ch->dev,
"Unable to allocate memory for READ LOG command\n"); "Unable to allocate memory for READ LOG command\n");
goto completeall; goto completeall;
} }
@ -1993,13 +1982,12 @@ ahci_issue_recovery(device_t dev)
/* Freeze SIM while doing recovery. */ /* Freeze SIM while doing recovery. */
ch->recoverycmd = 1; ch->recoverycmd = 1;
xpt_freeze_simq(ch->sim, 1); xpt_freeze_simq(ch->sim, 1);
ahci_begin_transaction(dev, ccb); ahci_begin_transaction(ch, ccb);
} }
static void static void
ahci_process_read_log(device_t dev, union ccb *ccb) ahci_process_read_log(struct ahci_channel *ch, union ccb *ccb)
{ {
struct ahci_channel *ch = device_get_softc(dev);
uint8_t *data; uint8_t *data;
struct ata_res *res; struct ata_res *res;
int i; int i;
@ -2037,9 +2025,9 @@ ahci_process_read_log(device_t dev, union ccb *ccb)
} }
} else { } else {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
device_printf(dev, "Error while READ LOG EXT\n"); device_printf(ch->dev, "Error while READ LOG EXT\n");
else if ((data[0] & 0x80) == 0) { else if ((data[0] & 0x80) == 0) {
device_printf(dev, "Non-queued command error in READ LOG EXT\n"); device_printf(ch->dev, "Non-queued command error in READ LOG EXT\n");
} }
for (i = 0; i < ch->numslots; i++) { for (i = 0; i < ch->numslots; i++) {
if (!ch->hold[i]) if (!ch->hold[i])
@ -2057,9 +2045,8 @@ ahci_process_read_log(device_t dev, union ccb *ccb)
} }
static void static void
ahci_process_request_sense(device_t dev, union ccb *ccb) ahci_process_request_sense(struct ahci_channel *ch, union ccb *ccb)
{ {
struct ahci_channel *ch = device_get_softc(dev);
int i; int i;
ch->recoverycmd = 0; ch->recoverycmd = 0;
@ -2079,9 +2066,8 @@ ahci_process_request_sense(device_t dev, union ccb *ccb)
} }
static void static void
ahci_start(device_t dev, int fbs) ahci_start(struct ahci_channel *ch, int fbs)
{ {
struct ahci_channel *ch = device_get_softc(dev);
u_int32_t cmd; u_int32_t cmd;
/* Clear SATA error register */ /* Clear SATA error register */
@ -2102,9 +2088,8 @@ ahci_start(device_t dev, int fbs)
} }
static void static void
ahci_stop(device_t dev) ahci_stop(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
u_int32_t cmd; u_int32_t cmd;
int timeout; int timeout;
@ -2116,7 +2101,7 @@ ahci_stop(device_t dev)
do { do {
DELAY(10); DELAY(10);
if (timeout++ > 50000) { if (timeout++ > 50000) {
device_printf(dev, "stopping AHCI engine failed\n"); device_printf(ch->dev, "stopping AHCI engine failed\n");
break; break;
} }
} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CR); } while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CR);
@ -2124,9 +2109,8 @@ ahci_stop(device_t dev)
} }
static void static void
ahci_clo(device_t dev) ahci_clo(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
u_int32_t cmd; u_int32_t cmd;
int timeout; int timeout;
@ -2139,7 +2123,7 @@ ahci_clo(device_t dev)
do { do {
DELAY(10); DELAY(10);
if (timeout++ > 50000) { if (timeout++ > 50000) {
device_printf(dev, "executing CLO failed\n"); device_printf(ch->dev, "executing CLO failed\n");
break; break;
} }
} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CLO); } while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CLO);
@ -2147,9 +2131,8 @@ ahci_clo(device_t dev)
} }
static void static void
ahci_stop_fr(device_t dev) ahci_stop_fr(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
u_int32_t cmd; u_int32_t cmd;
int timeout; int timeout;
@ -2161,16 +2144,15 @@ ahci_stop_fr(device_t dev)
do { do {
DELAY(10); DELAY(10);
if (timeout++ > 50000) { if (timeout++ > 50000) {
device_printf(dev, "stopping AHCI FR engine failed\n"); device_printf(ch->dev, "stopping AHCI FR engine failed\n");
break; break;
} }
} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_FR); } while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_FR);
} }
static void static void
ahci_start_fr(device_t dev) ahci_start_fr(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
u_int32_t cmd; u_int32_t cmd;
/* Start FIS reception on this channel */ /* Start FIS reception on this channel */
@ -2179,9 +2161,8 @@ ahci_start_fr(device_t dev)
} }
static int static int
ahci_wait_ready(device_t dev, int t, int t0) ahci_wait_ready(struct ahci_channel *ch, int t, int t0)
{ {
struct ahci_channel *ch = device_get_softc(dev);
int timeout = 0; int timeout = 0;
uint32_t val; uint32_t val;
@ -2189,7 +2170,7 @@ ahci_wait_ready(device_t dev, int t, int t0)
(ATA_S_BUSY | ATA_S_DRQ)) { (ATA_S_BUSY | ATA_S_DRQ)) {
if (timeout > t) { if (timeout > t) {
if (t != 0) { if (t != 0) {
device_printf(dev, device_printf(ch->dev,
"AHCI reset: device not ready after %dms " "AHCI reset: device not ready after %dms "
"(tfd = %08x)\n", "(tfd = %08x)\n",
MAX(t, 0) + t0, val); MAX(t, 0) + t0, val);
@ -2200,7 +2181,7 @@ ahci_wait_ready(device_t dev, int t, int t0)
timeout++; timeout++;
} }
if (bootverbose) if (bootverbose)
device_printf(dev, "AHCI reset: device ready after %dms\n", device_printf(ch->dev, "AHCI reset: device ready after %dms\n",
timeout + t0); timeout + t0);
return (0); return (0);
} }
@ -2208,22 +2189,21 @@ ahci_wait_ready(device_t dev, int t, int t0)
static void static void
ahci_reset_to(void *arg) ahci_reset_to(void *arg)
{ {
device_t dev = arg; struct ahci_channel *ch = arg;
struct ahci_channel *ch = device_get_softc(dev);
if (ch->resetting == 0) if (ch->resetting == 0)
return; return;
ch->resetting--; ch->resetting--;
if (ahci_wait_ready(dev, ch->resetting == 0 ? -1 : 0, if (ahci_wait_ready(ch, ch->resetting == 0 ? -1 : 0,
(310 - ch->resetting) * 100) == 0) { (310 - ch->resetting) * 100) == 0) {
ch->resetting = 0; ch->resetting = 0;
ahci_start(dev, 1); ahci_start(ch, 1);
xpt_release_simq(ch->sim, TRUE); xpt_release_simq(ch->sim, TRUE);
return; return;
} }
if (ch->resetting == 0) { if (ch->resetting == 0) {
ahci_clo(dev); ahci_clo(ch);
ahci_start(dev, 1); ahci_start(ch, 1);
xpt_release_simq(ch->sim, TRUE); xpt_release_simq(ch->sim, TRUE);
return; return;
} }
@ -2231,15 +2211,14 @@ ahci_reset_to(void *arg)
} }
static void static void
ahci_reset(device_t dev) ahci_reset(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev); struct ahci_controller *ctlr = device_get_softc(device_get_parent(ch->dev));
struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev));
int i; int i;
xpt_freeze_simq(ch->sim, 1); xpt_freeze_simq(ch->sim, 1);
if (bootverbose) if (bootverbose)
device_printf(dev, "AHCI reset...\n"); device_printf(ch->dev, "AHCI reset...\n");
/* Forget about previous reset. */ /* Forget about previous reset. */
if (ch->resetting) { if (ch->resetting) {
ch->resetting = 0; ch->resetting = 0;
@ -2258,7 +2237,7 @@ ahci_reset(device_t dev)
ahci_done(ch, fccb); ahci_done(ch, fccb);
} }
/* Kill the engine and requeue all running commands. */ /* Kill the engine and requeue all running commands. */
ahci_stop(dev); ahci_stop(ch);
for (i = 0; i < ch->numslots; i++) { for (i = 0; i < ch->numslots; i++) {
/* Do we have a running request on slot? */ /* Do we have a running request on slot? */
if (ch->slot[i].state < AHCI_SLOT_RUNNING) if (ch->slot[i].state < AHCI_SLOT_RUNNING)
@ -2284,9 +2263,9 @@ ahci_reset(device_t dev)
/* Disable port interrupts */ /* Disable port interrupts */
ATA_OUTL(ch->r_mem, AHCI_P_IE, 0); ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
/* Reset and reconnect PHY, */ /* Reset and reconnect PHY, */
if (!ahci_sata_phy_reset(dev)) { if (!ahci_sata_phy_reset(ch)) {
if (bootverbose) if (bootverbose)
device_printf(dev, device_printf(ch->dev,
"AHCI reset: device not found\n"); "AHCI reset: device not found\n");
ch->devices = 0; ch->devices = 0;
/* Enable wanted port interrupts */ /* Enable wanted port interrupts */
@ -2297,11 +2276,11 @@ ahci_reset(device_t dev)
return; return;
} }
if (bootverbose) if (bootverbose)
device_printf(dev, "AHCI reset: device found\n"); device_printf(ch->dev, "AHCI reset: device found\n");
/* Wait for clearing busy status. */ /* Wait for clearing busy status. */
if (ahci_wait_ready(dev, dumping ? 31000 : 0, 0)) { if (ahci_wait_ready(ch, dumping ? 31000 : 0, 0)) {
if (dumping) if (dumping)
ahci_clo(dev); ahci_clo(ch);
else else
ch->resetting = 310; ch->resetting = 310;
} }
@ -2315,17 +2294,16 @@ ahci_reset(device_t dev)
AHCI_P_IX_DP | AHCI_P_IX_UF | (ctlr->ccc ? 0 : AHCI_P_IX_SDB) | AHCI_P_IX_DP | AHCI_P_IX_UF | (ctlr->ccc ? 0 : AHCI_P_IX_SDB) |
AHCI_P_IX_DS | AHCI_P_IX_PS | (ctlr->ccc ? 0 : AHCI_P_IX_DHR))); AHCI_P_IX_DS | AHCI_P_IX_PS | (ctlr->ccc ? 0 : AHCI_P_IX_DHR)));
if (ch->resetting) if (ch->resetting)
callout_reset(&ch->reset_timer, hz / 10, ahci_reset_to, dev); callout_reset(&ch->reset_timer, hz / 10, ahci_reset_to, ch);
else { else {
ahci_start(dev, 1); ahci_start(ch, 1);
xpt_release_simq(ch->sim, TRUE); xpt_release_simq(ch->sim, TRUE);
} }
} }
static int static int
ahci_setup_fis(device_t dev, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag) ahci_setup_fis(struct ahci_channel *ch, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag)
{ {
struct ahci_channel *ch = device_get_softc(dev);
u_int8_t *fis = &ctp->cfis[0]; u_int8_t *fis = &ctp->cfis[0];
bzero(fis, 20); bzero(fis, 20);
@ -2417,9 +2395,8 @@ ahci_sata_connect(struct ahci_channel *ch)
} }
static int static int
ahci_sata_phy_reset(device_t dev) ahci_sata_phy_reset(struct ahci_channel *ch)
{ {
struct ahci_channel *ch = device_get_softc(dev);
int sata_rev; int sata_rev;
uint32_t val; uint32_t val;
@ -2459,9 +2436,8 @@ ahci_sata_phy_reset(device_t dev)
} }
static int static int
ahci_check_ids(device_t dev, union ccb *ccb) ahci_check_ids(struct ahci_channel *ch, union ccb *ccb)
{ {
struct ahci_channel *ch = device_get_softc(dev);
if (ccb->ccb_h.target_id > ((ch->caps & AHCI_CAP_SPM) ? 15 : 0)) { if (ccb->ccb_h.target_id > ((ch->caps & AHCI_CAP_SPM) ? 15 : 0)) {
ccb->ccb_h.status = CAM_TID_INVALID; ccb->ccb_h.status = CAM_TID_INVALID;
@ -2479,19 +2455,17 @@ ahci_check_ids(device_t dev, union ccb *ccb)
static void static void
ahciaction(struct cam_sim *sim, union ccb *ccb) ahciaction(struct cam_sim *sim, union ccb *ccb)
{ {
device_t dev, parent;
struct ahci_channel *ch; struct ahci_channel *ch;
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahciaction func_code=%x\n", CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahciaction func_code=%x\n",
ccb->ccb_h.func_code)); ccb->ccb_h.func_code));
ch = (struct ahci_channel *)cam_sim_softc(sim); ch = (struct ahci_channel *)cam_sim_softc(sim);
dev = ch->dev;
switch (ccb->ccb_h.func_code) { switch (ccb->ccb_h.func_code) {
/* Common cases first */ /* Common cases first */
case XPT_ATA_IO: /* Execute the requested I/O operation */ case XPT_ATA_IO: /* Execute the requested I/O operation */
case XPT_SCSI_IO: case XPT_SCSI_IO:
if (ahci_check_ids(dev, ccb)) if (ahci_check_ids(ch, ccb))
return; return;
if (ch->devices == 0 || if (ch->devices == 0 ||
(ch->pm_present == 0 && (ch->pm_present == 0 &&
@ -2501,14 +2475,14 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
} }
ccb->ccb_h.recovery_type = RECOVERY_NONE; ccb->ccb_h.recovery_type = RECOVERY_NONE;
/* Check for command collision. */ /* Check for command collision. */
if (ahci_check_collision(dev, ccb)) { if (ahci_check_collision(ch, ccb)) {
/* Freeze command. */ /* Freeze command. */
ch->frozen = ccb; ch->frozen = ccb;
/* We have only one frozen slot, so freeze simq also. */ /* We have only one frozen slot, so freeze simq also. */
xpt_freeze_simq(ch->sim, 1); xpt_freeze_simq(ch->sim, 1);
return; return;
} }
ahci_begin_transaction(dev, ccb); ahci_begin_transaction(ch, ccb);
return; return;
case XPT_EN_LUN: /* Enable LUN as a target */ case XPT_EN_LUN: /* Enable LUN as a target */
case XPT_TARGET_IO: /* Execute target I/O request */ case XPT_TARGET_IO: /* Execute target I/O request */
@ -2523,7 +2497,7 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts = &ccb->cts; struct ccb_trans_settings *cts = &ccb->cts;
struct ahci_device *d; struct ahci_device *d;
if (ahci_check_ids(dev, ccb)) if (ahci_check_ids(ch, ccb))
return; return;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS) if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
d = &ch->curr[ccb->ccb_h.target_id]; d = &ch->curr[ccb->ccb_h.target_id];
@ -2553,7 +2527,7 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
struct ahci_device *d; struct ahci_device *d;
uint32_t status; uint32_t status;
if (ahci_check_ids(dev, ccb)) if (ahci_check_ids(ch, ccb))
return; return;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS) if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
d = &ch->curr[ccb->ccb_h.target_id]; d = &ch->curr[ccb->ccb_h.target_id];
@ -2610,7 +2584,7 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
} }
case XPT_RESET_BUS: /* Reset the specified SCSI bus */ case XPT_RESET_BUS: /* Reset the specified SCSI bus */
case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
ahci_reset(dev); ahci_reset(ch);
ccb->ccb_h.status = CAM_REQ_CMP; ccb->ccb_h.status = CAM_REQ_CMP;
break; break;
case XPT_TERM_IO: /* Terminate the I/O process */ case XPT_TERM_IO: /* Terminate the I/O process */
@ -2621,7 +2595,6 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
{ {
struct ccb_pathinq *cpi = &ccb->cpi; struct ccb_pathinq *cpi = &ccb->cpi;
parent = device_get_parent(dev);
cpi->version_num = 1; /* XXX??? */ cpi->version_num = 1; /* XXX??? */
cpi->hba_inquiry = PI_SDTR_ABLE; cpi->hba_inquiry = PI_SDTR_ABLE;
if (ch->caps & AHCI_CAP_SNCQ) if (ch->caps & AHCI_CAP_SNCQ)
@ -2678,7 +2651,7 @@ ahcipoll(struct cam_sim *sim)
if (ch->resetting != 0 && if (ch->resetting != 0 &&
(--ch->resetpolldiv <= 0 || !callout_pending(&ch->reset_timer))) { (--ch->resetpolldiv <= 0 || !callout_pending(&ch->reset_timer))) {
ch->resetpolldiv = 1000; ch->resetpolldiv = 1000;
ahci_reset_to(ch->dev); ahci_reset_to(ch);
} }
} }
MODULE_VERSION(ahci, 1); MODULE_VERSION(ahci, 1);

View File

@ -375,7 +375,7 @@ enum ahci_slot_states {
}; };
struct ahci_slot { struct ahci_slot {
device_t dev; /* Device handle */ struct ahci_channel *ch; /* Channel */
u_int8_t slot; /* Number of this slot */ u_int8_t slot; /* Number of this slot */
enum ahci_slot_states state; /* Slot state */ enum ahci_slot_states state; /* Slot state */
union ccb *ccb; /* CCB occupying slot */ union ccb *ccb; /* CCB occupying slot */
@ -422,20 +422,19 @@ struct ahci_channel {
int quirks; int quirks;
int numslots; /* Number of present slots */ int numslots; /* Number of present slots */
int pm_level; /* power management level */ int pm_level; /* power management level */
struct ahci_slot slot[AHCI_MAX_SLOTS];
union ccb *hold[AHCI_MAX_SLOTS];
struct mtx mtx; /* state lock */
STAILQ_HEAD(, ccb_hdr) doneq; /* queue of completed CCBs */
int batch; /* doneq is in use */
int devices; /* What is present */ int devices; /* What is present */
int pm_present; /* PM presence reported */ int pm_present; /* PM presence reported */
int fbs_enabled; /* FIS-based switching enabled */ int fbs_enabled; /* FIS-based switching enabled */
union ccb *hold[AHCI_MAX_SLOTS];
struct ahci_slot slot[AHCI_MAX_SLOTS];
uint32_t oslots; /* Occupied slots */ uint32_t oslots; /* Occupied slots */
uint32_t rslots; /* Running slots */ uint32_t rslots; /* Running slots */
uint32_t aslots; /* Slots with atomic commands */ uint32_t aslots; /* Slots with atomic commands */
uint32_t eslots; /* Slots in error */ uint32_t eslots; /* Slots in error */
uint32_t toslots; /* Slots in timeout */ uint32_t toslots; /* Slots in timeout */
int lastslot; /* Last used slot */
int taggedtarget; /* Last tagged target */
int numrslots; /* Number of running slots */ int numrslots; /* Number of running slots */
int numrslotspd[16];/* Number of running slots per dev */ int numrslotspd[16];/* Number of running slots per dev */
int numtslots; /* Number of tagged slots */ int numtslots; /* Number of tagged slots */
@ -443,8 +442,6 @@ struct ahci_channel {
int numhslots; /* Number of held slots */ int numhslots; /* Number of held slots */
int recoverycmd; /* Our READ LOG active */ int recoverycmd; /* Our READ LOG active */
int fatalerr; /* Fatal error happend */ int fatalerr; /* Fatal error happend */
int lastslot; /* Last used slot */
int taggedtarget; /* Last tagged target */
int resetting; /* Hard-reset in progress. */ int resetting; /* Hard-reset in progress. */
int resetpolldiv; /* Hard-reset poll divider. */ int resetpolldiv; /* Hard-reset poll divider. */
int listening; /* SUD bit is cleared. */ int listening; /* SUD bit is cleared. */
@ -455,6 +452,10 @@ struct ahci_channel {
struct ahci_device user[16]; /* User-specified settings */ struct ahci_device user[16]; /* User-specified settings */
struct ahci_device curr[16]; /* Current settings */ struct ahci_device curr[16]; /* Current settings */
struct mtx_padalign mtx; /* state lock */
STAILQ_HEAD(, ccb_hdr) doneq; /* queue of completed CCBs */
int batch; /* doneq is in use */
}; };
struct ahci_enclosure { struct ahci_enclosure {

View File

@ -344,7 +344,7 @@ ahci_em_led(void *priv, int onoff)
} }
static int static int
ahci_check_ids(device_t dev, union ccb *ccb) ahci_check_ids(union ccb *ccb)
{ {
if (ccb->ccb_h.target_id != 0) { if (ccb->ccb_h.target_id != 0) {
@ -554,7 +554,7 @@ ahciemaction(struct cam_sim *sim, union ccb *ccb)
dev = enc->dev; dev = enc->dev;
switch (ccb->ccb_h.func_code) { switch (ccb->ccb_h.func_code) {
case XPT_ATA_IO: /* Execute the requested I/O operation */ case XPT_ATA_IO: /* Execute the requested I/O operation */
if (ahci_check_ids(dev, ccb)) if (ahci_check_ids(ccb))
return; return;
ahci_em_begin_transaction(dev, ccb); ahci_em_begin_transaction(dev, ccb);
return; return;