PERFORCE change 164261 for review
Alexander Motin
mav at FreeBSD.org
Sat Jun 13 11:50:26 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=164261
Change 164261 by mav at 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 */
More information about the p4-projects
mailing list