From owner-p4-projects@FreeBSD.ORG Sat Jun 13 11:50:25 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7EE301065674; Sat, 13 Jun 2009 11:50:25 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3CCD6106564A for ; Sat, 13 Jun 2009 11:50:25 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 29BBE8FC0A for ; Sat, 13 Jun 2009 11:50:25 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n5DBoPkc015968 for ; Sat, 13 Jun 2009 11:50:25 GMT (envelope-from mav@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n5DBoPAm015966 for perforce@freebsd.org; Sat, 13 Jun 2009 11:50:25 GMT (envelope-from mav@freebsd.org) Date: Sat, 13 Jun 2009 11:50:25 GMT Message-Id: <200906131150.n5DBoPAm015966@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to mav@freebsd.org using -f From: Alexander Motin To: Perforce Change Reviews Cc: Subject: PERFORCE change 164261 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 13 Jun 2009 11:50:26 -0000 http://perforce.freebsd.org/chv.cgi?CH=164261 Change 164261 by mav@mav_mavbook on 2009/06/13 11:49:27 Make Soft Reset sequence to be an atomic operation for XPT. SiI HBAs to it completely in silicon. Affected files ... .. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#14 edit .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#23 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#14 (text+ko) ==== @@ -92,7 +92,6 @@ typedef enum { PROBE_RESET, - PROBE_UNRESET, PROBE_IDENTIFY, PROBE_INQUIRY, PROBE_FULL_INQUIRY, @@ -101,7 +100,6 @@ static char *probe_action_text[] = { "PROBE_RESET", - "PROBE_UNRESET", "PROBE_IDENTIFY", "PROBE_INQUIRY", "PROBE_FULL_INQUIRY", @@ -281,8 +279,8 @@ * delay before attempting to probe the device. * For HBAs that don't do bus resets, this won't make a difference. */ -// cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, -// scsi_delay); + cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, + scsi_delay); probeschedule(periph); return(CAM_REQ_CMP); } @@ -330,7 +328,6 @@ switch (softc->action) { case PROBE_RESET: - case PROBE_UNRESET: cam_fill_ataio(ataio, 4, probedone, @@ -339,7 +336,7 @@ /*data_ptr*/NULL, /*dxfer_len*/0, 30 * 1000); - ata_reset_cmd(ataio, softc->action == PROBE_RESET ? 1 : 0); + ata_reset_cmd(ataio, 1); break; case PROBE_IDENTIFY: { @@ -559,25 +556,6 @@ switch (softc->action) { case PROBE_RESET: if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - PROBE_SET_ACTION(softc, PROBE_UNRESET); - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } else if (cam_periph_error(done_ccb, 0, - done_ccb->ccb_h.target_lun > 0 - ? SF_RETRY_UA|SF_QUIET_IR - : SF_RETRY_UA, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - xpt_release_ccb(done_ccb); - break; - case PROBE_UNRESET: - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { printf("SIGNATURE: %02x%02x%02x%02x\n", done_ccb->ataio.res.lba_high, done_ccb->ataio.res.lba_mid, done_ccb->ataio.res.lba_low, done_ccb->ataio.res.sector_count); ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#23 (text+ko) ==== @@ -69,7 +69,7 @@ static void ahci_execute_transaction(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 int ahci_hardreset(device_t dev, int port, uint32_t *signature); +static int ahci_hardreset(device_t dev); static int ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag); static void ahci_dmainit(device_t dev); static void ahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); @@ -79,7 +79,7 @@ static void ahci_reset(device_t dev); static void ahci_start(device_t dev); static void ahci_stop(device_t dev); -//static void ahci_clo(device_t dev); +static void ahci_clo(device_t dev); static void ahci_start_fr(device_t dev); static void ahci_stop_fr(device_t dev); @@ -848,6 +848,7 @@ >> AHCI_P_CMD_CCS_SHIFT; /* Kick controller into sane state */ ahci_stop(dev); + ahci_clo(dev); ahci_start(dev); res = ch->rslots; err = ch->rslots & (cstatus | sstatus); @@ -1030,6 +1031,10 @@ if ((ccb->ccb_h.func_code == XPT_ATA_IO) && (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) && ccb->ataio.cmd.control & ATA_A_RESET) { + /* Kick controller into sane state */ + ahci_stop(dev); + ahci_clo(dev); + ahci_start(dev); clp->cmd_flags |= AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY; } clp->bytecount = 0; @@ -1080,6 +1085,7 @@ et = CAM_CMD_TIMEOUT; /* Kick controller into sane state */ ahci_stop(ch->dev); + ahci_clo(ch->dev); ahci_start(ch->dev); } ahci_end_transaction(slot, et); @@ -1172,33 +1178,34 @@ bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map); } /* Set proper result status. */ + ccb->ccb_h.status &= ~CAM_STATUS_MASK; switch (et) { case AHCI_ERR_NONE: - ccb->ccb_h.status = CAM_REQ_CMP; + ccb->ccb_h.status |= CAM_REQ_CMP; if (ccb->ccb_h.func_code == XPT_SCSI_IO) ccb->csio.scsi_status = SCSI_STATUS_OK; break; case AHCI_ERR_INVALID: - ccb->ccb_h.status = CAM_REQ_INVALID; + ccb->ccb_h.status |= CAM_REQ_INVALID; break; case AHCI_ERR_REAL: if (ccb->ccb_h.func_code == XPT_SCSI_IO) { - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; + ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; } else - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + ccb->ccb_h.status |= CAM_REQ_CMP_ERR; break; case AHCI_ERR_BTW: - ccb->ccb_h.status = CAM_REQUEUE_REQ; + ccb->ccb_h.status |= CAM_REQUEUE_REQ; break; case AHCI_ERR_RESET: - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; + ccb->ccb_h.status |= CAM_SCSI_BUS_RESET; break; case AHCI_ERR_TIMEOUT: - ccb->ccb_h.status = CAM_CMD_TIMEOUT; + ccb->ccb_h.status |= CAM_CMD_TIMEOUT; break; default: - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + ccb->ccb_h.status |= CAM_REQ_CMP_ERR; } /* Free slot. */ ch->rslots &= ~(1 << slot->slot); @@ -1210,13 +1217,27 @@ (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) { ch->numtslots--; } + /* If it was first request of reset sequence nod no error, + * proceed to second. */ + if ((ccb->ccb_h.func_code == XPT_ATA_IO) && + (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) && + (ccb->ataio.cmd.control & ATA_A_RESET) && + et == AHCI_ERR_NONE) { + ccb->ataio.cmd.control &= ~ATA_A_RESET; + ahci_begin_transaction(dev, ccb); + return; + } xpt_done(ccb); if (ch->frozen && ch->numrslots == 0) { union ccb *fccb = ch->frozen; //device_printf(dev, "Unfreeze\n"); ch->frozen = NULL; ahci_begin_transaction(dev, fccb); - xpt_release_simq(ch->sim, TRUE); + /* If frozen command is not reset - release queue. + * Reset will be released after it is finished. */ + if ((fccb->ccb_h.func_code == XPT_ATA_IO) && + (fccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) == 0) + xpt_release_simq(ch->sim, TRUE); } } @@ -1227,12 +1248,12 @@ u_int32_t cmd; /* Clear SATA error register */ - ATA_OUTL(ch->r_mem, AHCI_P_SERR, ATA_INL(ch->r_mem, AHCI_P_SERR)); + ATA_OUTL(ch->r_mem, AHCI_P_SERR, 0xFFFFFFFF); /* Clear any interrupts pending on this channel */ - ATA_OUTL(ch->r_mem, AHCI_P_IS, ATA_INL(ch->r_mem, AHCI_P_IS)); + ATA_OUTL(ch->r_mem, AHCI_P_IS, 0xFFFFFFFF); /* Start operations on this channel */ cmd = ATA_INL(ch->r_mem, AHCI_P_CMD); - ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd | AHCI_P_CMD_ST); + ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd | AHCI_P_CMD_ST | AHCI_P_CMD_PMA); // (ch->devices & ATA_PORTMULTIPLIER ? AHCI_P_CMD_PMA : 0)); } @@ -1257,7 +1278,6 @@ } while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CR); } -#if 0 static void ahci_clo(device_t dev) { @@ -1280,7 +1300,6 @@ } while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CLO); } } -#endif static void ahci_stop_fr(device_t dev) @@ -1336,23 +1355,19 @@ } static int -ahci_hardreset(device_t dev, int port, uint32_t *signature) +ahci_hardreset(device_t dev) { - struct ahci_channel *ch = device_get_softc(dev); - *signature = 0xffffffff; ahci_stop(dev); /* Reset port */ if (!ahci_sata_phy_reset(dev, 0)) return (ENOENT); /* Wait for clearing busy status. */ if (ahci_wait_ready(dev, 10000)) { - device_printf(dev, "hardware reset timeout\n"); - return (EBUSY); + device_printf(dev, "device ready timeout\n"); + ahci_clo(dev); } - *signature = ATA_INL(ch->r_mem, AHCI_P_SIG); ahci_start(dev); - return (0); } @@ -1360,7 +1375,6 @@ ahci_reset(device_t dev) { struct ahci_channel *ch = device_get_softc(dev); - u_int32_t signature; if (bootverbose) device_printf(dev, "AHCI reset...\n"); @@ -1368,7 +1382,7 @@ /* Disable port interrupts */ ATA_OUTL(ch->r_mem, AHCI_P_IE, 0); /* Reset and reconnect PHY, */ - if (ahci_hardreset(dev, -1, &signature)) { + if (ahci_hardreset(dev)) { if (bootverbose) device_printf(dev, "AHCI reset done: phy reset found no device\n"); @@ -1448,8 +1462,8 @@ u_int32_t status; int timeout; - /* Wait up to 1 second for "connect well" */ - for (timeout = 0; timeout < 1000 ; timeout++) { + /* Wait up to 100ms for "connect well" */ + for (timeout = 0; timeout < 100 ; timeout++) { status = ATA_INL(ch->r_mem, AHCI_P_SSTS); if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) && ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) && @@ -1457,7 +1471,7 @@ break; DELAY(1000); } - if (timeout >= 1000) { + if (timeout >= 100) { if (bootverbose) { device_printf(ch->dev, "SATA connect timeout status=%08x\n", status); @@ -1487,11 +1501,13 @@ if (bootverbose) device_printf(dev, "hardware reset ...\n"); - ATA_OUTL(ch->r_mem, AHCI_P_SCTL, ATA_SC_DET_RESET); + ATA_OUTL(ch->r_mem, AHCI_P_SCTL, ATA_SC_IPM_DIS_PARTIAL | + ATA_SC_IPM_DIS_SLUMBER | ATA_SC_DET_RESET); DELAY(50000); ATA_OUTL(ch->r_mem, AHCI_P_SCTL, - ATA_SC_DET_IDLE /*| ATA_SC_SPD_SPEED_GEN1*/ | ((ch->pm_level > 0) ? 0 : + ATA_SC_DET_IDLE | ATA_SC_SPD_SPEED_GEN1 | ((ch->pm_level > 0) ? 0 : (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))); + DELAY(50000); return (ahci_sata_connect(ch)); } @@ -1519,12 +1535,18 @@ /* Check for command collision. */ if (ahci_check_collision(dev, ccb)) { /* Freeze command. */ -device_printf(dev, "Freeze\n"); +//device_printf(dev, "Freeze\n"); /* We have only one frozen slot, so freeze simq also. */ xpt_freeze_simq(ch->sim, 1); ch->frozen = ccb; return; } + /* If it is a reset sequence - freeze the queue. */ + if ((ccb->ccb_h.func_code == XPT_ATA_IO) && + (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) { + xpt_freeze_simq(ch->sim, 1); + ccb->ccb_h.status |= CAM_RELEASE_SIMQ; + } ahci_begin_transaction(dev, ccb); break; case XPT_EN_LUN: /* Enable LUN as a target */