Date: Tue, 19 Apr 2011 17:06:43 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r220857 - stable/8/sys/dev/siis Message-ID: <201104191706.p3JH6hbr015829@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Tue Apr 19 17:06:43 2011 New Revision: 220857 URL: http://svn.freebsd.org/changeset/base/220857 Log: MFC r220566: Implement automatic SCSI sense fetching for siis(4). Fix device freeze leak on recovery request (READ LOG, REQUEST SENSE) failure. Modified: stable/8/sys/dev/siis/siis.c stable/8/sys/dev/siis/siis.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) Modified: stable/8/sys/dev/siis/siis.c ============================================================================== --- stable/8/sys/dev/siis/siis.c Tue Apr 19 17:04:58 2011 (r220856) +++ stable/8/sys/dev/siis/siis.c Tue Apr 19 17:06:43 2011 (r220857) @@ -84,8 +84,9 @@ static int siis_wait_ready(device_t dev, static int siis_sata_connect(struct siis_channel *ch); -static void siis_issue_read_log(device_t dev); +static void siis_issue_recovery(device_t dev); static void siis_process_read_log(device_t dev, union ccb *ccb); +static void siis_process_request_sense(device_t dev, union ccb *ccb); static void siisaction(struct cam_sim *sim, union ccb *ccb); static void siispoll(struct cam_sim *sim); @@ -110,6 +111,12 @@ static struct { {0, NULL, 0, 0} }; +#define recovery_type spriv_field0 +#define RECOVERY_NONE 0 +#define RECOVERY_READ_LOG 1 +#define RECOVERY_REQUEST_SENSE 2 +#define recovery_slot spriv_field1 + static int siis_probe(device_t dev) { @@ -873,7 +880,7 @@ siis_ch_intr(void *data) // __func__, sstatus, istatus, ch->rslots, estatus, ccs, port, // ATA_INL(ch->r_mem, SIIS_P_SERR)); - if (!ch->readlog && !ch->recovery) { + if (!ch->recoverycmd && !ch->recovery) { xpt_freeze_simq(ch->sim, ch->numrslots); ch->recovery = 1; } @@ -914,7 +921,7 @@ siis_ch_intr(void *data) * We can't reinit port if there are some other * commands active, use resume to complete them. */ - if (ch->rslots != 0) + if (ch->rslots != 0 && !ch->recoverycmd) ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_RESUME); } else { if (estatus == SIIS_P_CMDERR_SENDFIS || @@ -1021,7 +1028,7 @@ siis_dmasetprd(void *arg, bus_dma_segmen mtx_assert(&ch->mtx, MA_OWNED); if (error) { device_printf(slot->dev, "DMA load error\n"); - if (!ch->readlog) + if (!ch->recoverycmd) xpt_freeze_simq(ch->sim, 1); siis_end_transaction(slot, SIIS_ERR_INVALID); return; @@ -1101,7 +1108,7 @@ siis_execute_transaction(struct siis_slo /* Setup the FIS for this request */ if (!siis_setup_fis(dev, ctp, ccb, slot->slot)) { device_printf(ch->dev, "Setting up SATA FIS failed\n"); - if (!ch->readlog) + if (!ch->recoverycmd) xpt_freeze_simq(ch->sim, 1); siis_end_transaction(slot, SIIS_ERR_INVALID); return; @@ -1129,7 +1136,7 @@ siis_process_timeout(device_t dev) int i; mtx_assert(&ch->mtx, MA_OWNED); - if (!ch->readlog && !ch->recovery) { + if (!ch->recoverycmd && !ch->recovery) { xpt_freeze_simq(ch->sim, ch->numrslots); ch->recovery = 1; } @@ -1251,7 +1258,7 @@ siis_end_transaction(struct siis_slot *s ccb->ccb_h.status |= CAM_RELEASE_SIMQ; } /* In case of error, freeze device for proper recovery. */ - if (et != SIIS_ERR_NONE && + if (et != SIIS_ERR_NONE && (!ch->recoverycmd) && !(ccb->ccb_h.status & CAM_DEV_QFRZN)) { xpt_freeze_devq(ccb->ccb_h.path, 1); ccb->ccb_h.status |= CAM_DEV_QFRZN; @@ -1310,10 +1317,15 @@ siis_end_transaction(struct siis_slot *s xpt_release_simq(ch->sim, TRUE); } /* If it was our READ LOG command - process it. */ - if (ch->readlog) { + if (ccb->ccb_h.recovery_type == RECOVERY_READ_LOG) { siis_process_read_log(dev, ccb); - /* If it was NCQ command error, put result on hold. */ - } else if (et == SIIS_ERR_NCQ) { + /* If it was our REQUEST SENSE command - process it. */ + } else if (ccb->ccb_h.recovery_type == RECOVERY_REQUEST_SENSE) { + siis_process_request_sense(dev, ccb); + /* If it was NCQ or ATAPI command error, put result on hold. */ + } else if (et == SIIS_ERR_NCQ || + ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR && + (ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)) { ch->hold[slot->slot] = ccb; ch->numhslots++; } else @@ -1334,9 +1346,9 @@ siis_end_transaction(struct siis_slot *s /* if we have slots in error, we can reinit port. */ if (ch->eslots != 0) siis_portinit(dev); - /* if there commands on hold, we can do READ LOG. */ - if (!ch->readlog && ch->numhslots) - siis_issue_read_log(dev); + /* if there commands on hold, we can do recovery. */ + if (!ch->recoverycmd && ch->numhslots) + siis_issue_recovery(dev); } /* If all the reset of commands are in timeout - abort them. */ } else if ((ch->rslots & ~ch->toslots) == 0 && @@ -1345,11 +1357,12 @@ siis_end_transaction(struct siis_slot *s } static void -siis_issue_read_log(device_t dev) +siis_issue_recovery(device_t dev) { struct siis_channel *ch = device_get_softc(dev); union ccb *ccb; struct ccb_ataio *ataio; + struct ccb_scsiio *csio; int i; /* Find some holden command. */ @@ -1359,32 +1372,51 @@ siis_issue_read_log(device_t dev) } if (i == SIIS_MAX_SLOTS) return; - ch->readlog = 1; + ch->recoverycmd = 1; ccb = xpt_alloc_ccb_nowait(); if (ccb == NULL) { device_printf(dev, "Unable allocate READ LOG command"); return; /* XXX */ } ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */ - ccb->ccb_h.func_code = XPT_ATA_IO; - ccb->ccb_h.flags = CAM_DIR_IN; - ccb->ccb_h.timeout = 1000; /* 1s should be enough. */ - ataio = &ccb->ataio; - ataio->data_ptr = malloc(512, M_SIIS, M_NOWAIT); - if (ataio->data_ptr == NULL) { - xpt_free_ccb(ccb); - device_printf(dev, "Unable allocate memory for READ LOG command"); - return; /* XXX */ + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + /* READ LOG */ + ccb->ccb_h.recovery_type = RECOVERY_READ_LOG; + ccb->ccb_h.func_code = XPT_ATA_IO; + ccb->ccb_h.flags = CAM_DIR_IN; + ccb->ccb_h.timeout = 1000; /* 1s should be enough. */ + ataio = &ccb->ataio; + ataio->data_ptr = malloc(512, M_SIIS, M_NOWAIT); + if (ataio->data_ptr == NULL) { + xpt_free_ccb(ccb); + device_printf(dev, "Unable allocate memory for READ LOG command"); + return; /* XXX */ + } + ataio->dxfer_len = 512; + bzero(&ataio->cmd, sizeof(ataio->cmd)); + ataio->cmd.flags = CAM_ATAIO_48BIT; + ataio->cmd.command = 0x2F; /* READ LOG EXT */ + ataio->cmd.sector_count = 1; + ataio->cmd.sector_count_exp = 0; + ataio->cmd.lba_low = 0x10; + ataio->cmd.lba_mid = 0; + ataio->cmd.lba_mid_exp = 0; + } else { + /* REQUEST SENSE */ + ccb->ccb_h.recovery_type = RECOVERY_REQUEST_SENSE; + ccb->ccb_h.recovery_slot = i; + ccb->ccb_h.func_code = XPT_SCSI_IO; + ccb->ccb_h.flags = CAM_DIR_IN; + ccb->ccb_h.status = 0; + ccb->ccb_h.timeout = 1000; /* 1s should be enough. */ + csio = &ccb->csio; + csio->data_ptr = (void *)&ch->hold[i]->csio.sense_data; + csio->dxfer_len = ch->hold[i]->csio.sense_len; + csio->cdb_len = 6; + bzero(&csio->cdb_io, sizeof(csio->cdb_io)); + csio->cdb_io.cdb_bytes[0] = 0x03; + csio->cdb_io.cdb_bytes[4] = csio->dxfer_len; } - ataio->dxfer_len = 512; - bzero(&ataio->cmd, sizeof(ataio->cmd)); - ataio->cmd.flags = CAM_ATAIO_48BIT; - ataio->cmd.command = 0x2F; /* READ LOG EXT */ - ataio->cmd.sector_count = 1; - ataio->cmd.sector_count_exp = 0; - ataio->cmd.lba_low = 0x10; - ataio->cmd.lba_mid = 0; - ataio->cmd.lba_mid_exp = 0; siis_begin_transaction(dev, ccb); } @@ -1396,7 +1428,7 @@ siis_process_read_log(device_t dev, unio struct ata_res *res; int i; - ch->readlog = 0; + ch->recoverycmd = 0; data = ccb->ataio.data_ptr; if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && (data[0] & 0x80) == 0) { @@ -1447,6 +1479,27 @@ siis_process_read_log(device_t dev, unio } static void +siis_process_request_sense(device_t dev, union ccb *ccb) +{ + struct siis_channel *ch = device_get_softc(dev); + int i; + + ch->recoverycmd = 0; + + i = ccb->ccb_h.recovery_slot; + if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + ch->hold[i]->ccb_h.status |= CAM_AUTOSNS_VALID; + } else { + ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK; + ch->hold[i]->ccb_h.status |= CAM_AUTOSENSE_FAIL; + } + xpt_done(ch->hold[i]); + ch->hold[i] = NULL; + ch->numhslots--; + xpt_free_ccb(ccb); +} + +static void siis_portinit(device_t dev) { struct siis_channel *ch = device_get_softc(dev); @@ -1512,7 +1565,7 @@ siis_reset(device_t dev) xpt_freeze_simq(ch->sim, 1); if (bootverbose) device_printf(dev, "SIIS reset...\n"); - if (!ch->readlog && !ch->recovery) + if (!ch->recoverycmd && !ch->recovery) xpt_freeze_simq(ch->sim, ch->numrslots); /* Requeue frozen command. */ if (ch->frozen) { @@ -1732,6 +1785,7 @@ siisaction(struct cam_sim *sim, union cc ccb->ccb_h.status = CAM_SEL_TIMEOUT; break; } + ccb->ccb_h.recovery_type = RECOVERY_NONE; /* Check for command collision. */ if (siis_check_collision(dev, ccb)) { /* Freeze command. */ Modified: stable/8/sys/dev/siis/siis.h ============================================================================== --- stable/8/sys/dev/siis/siis.h Tue Apr 19 17:04:58 2011 (r220856) +++ stable/8/sys/dev/siis/siis.h Tue Apr 19 17:06:43 2011 (r220857) @@ -388,7 +388,7 @@ struct siis_channel { int numrslots; /* Number of running slots */ int numtslots[SIIS_MAX_SLOTS]; /* Number of tagged slots */ int numhslots; /* Number of holden slots */ - int readlog; /* Our READ LOG active */ + int recoverycmd; /* Our READ LOG active */ int fatalerr; /* Fatal error happend */ int recovery; /* Some slots are in error */ union ccb *frozen; /* Frozen command */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104191706.p3JH6hbr015829>