From owner-svn-src-all@FreeBSD.ORG Tue Apr 12 11:25:00 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2EC56106564A; Tue, 12 Apr 2011 11:25:00 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 1C9A88FC0A; Tue, 12 Apr 2011 11:25:00 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p3CBP08u022785; Tue, 12 Apr 2011 11:25:00 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p3CBOxw7022782; Tue, 12 Apr 2011 11:24:59 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201104121124.p3CBOxw7022782@svn.freebsd.org> From: Alexander Motin Date: Tue, 12 Apr 2011 11:24:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r220565 - head/sys/dev/ahci X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Apr 2011 11:25:00 -0000 Author: mav Date: Tue Apr 12 11:24:59 2011 New Revision: 220565 URL: http://svn.freebsd.org/changeset/base/220565 Log: Implement automatic SCSI sense fetching for ahci(4). Modified: head/sys/dev/ahci/ahci.c head/sys/dev/ahci/ahci.h Modified: head/sys/dev/ahci/ahci.c ============================================================================== --- head/sys/dev/ahci/ahci.c Tue Apr 12 11:17:46 2011 (r220564) +++ head/sys/dev/ahci/ahci.c Tue Apr 12 11:24:59 2011 (r220565) @@ -91,8 +91,9 @@ static int ahci_sata_connect(struct ahci static int ahci_sata_phy_reset(device_t dev); static int ahci_wait_ready(device_t dev, int t); -static void ahci_issue_read_log(device_t dev); +static void ahci_issue_recovery(device_t dev); static void ahci_process_read_log(device_t dev, union ccb *ccb); +static void ahci_process_request_sense(device_t dev, union ccb *ccb); static void ahciaction(struct cam_sim *sim, union ccb *ccb); static void ahcipoll(struct cam_sim *sim); @@ -267,6 +268,12 @@ static struct { {0x00000000, 0x00, NULL, 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 ahci_probe(device_t dev) { @@ -1465,7 +1472,7 @@ ahci_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, AHCI_P_FBS, AHCI_P_FBS_EN | AHCI_P_FBS_DEC); } /* Process NOTIFY events */ @@ -1937,7 +1944,7 @@ ahci_end_transaction(struct ahci_slot *s if (et != AHCI_ERR_NONE) ch->eslots |= (1 << slot->slot); /* In case of error, freeze device for proper recovery. */ - if ((et != AHCI_ERR_NONE) && (!ch->readlog) && + if ((et != AHCI_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; @@ -1968,7 +1975,7 @@ ahci_end_transaction(struct ahci_slot *s break; case AHCI_ERR_SATA: ch->fatalerr = 1; - if (!ch->readlog) { + if (!ch->recoverycmd) { xpt_freeze_simq(ch->sim, 1); ccb->ccb_h.status &= ~CAM_STATUS_MASK; ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -1976,7 +1983,7 @@ ahci_end_transaction(struct ahci_slot *s ccb->ccb_h.status |= CAM_UNCOR_PARITY; break; case AHCI_ERR_TIMEOUT: - if (!ch->readlog) { + if (!ch->recoverycmd) { xpt_freeze_simq(ch->sim, 1); ccb->ccb_h.status &= ~CAM_STATUS_MASK; ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -2019,10 +2026,15 @@ ahci_end_transaction(struct ahci_slot *s return; } /* If it was our READ LOG command - process it. */ - if (ch->readlog) { + if (ccb->ccb_h.recovery_type == RECOVERY_READ_LOG) { ahci_process_read_log(dev, ccb); - /* If it was NCQ command error, put result on hold. */ - } else if (et == AHCI_ERR_NCQ) { + /* If it was our REQUEST SENSE command - process it. */ + } else if (ccb->ccb_h.recovery_type == RECOVERY_REQUEST_SENSE) { + ahci_process_request_sense(dev, ccb); + /* If it was NCQ or ATAPI command error, put result on hold. */ + } else if (et == AHCI_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 @@ -2046,8 +2058,8 @@ ahci_end_transaction(struct ahci_slot *s ahci_start(dev, 1); } /* if there commands on hold, we can do READ LOG. */ - if (!ch->readlog && ch->numhslots) - ahci_issue_read_log(dev); + if (!ch->recoverycmd && ch->numhslots) + ahci_issue_recovery(dev); } /* If all the rest of commands are in timeout - give them chance. */ } else if ((ch->rslots & ~ch->toslots) == 0 && @@ -2062,14 +2074,15 @@ ahci_end_transaction(struct ahci_slot *s } static void -ahci_issue_read_log(device_t dev) +ahci_issue_recovery(device_t dev) { struct ahci_channel *ch = device_get_softc(dev); union ccb *ccb; struct ccb_ataio *ataio; + struct ccb_scsiio *csio; int i; - ch->readlog = 1; + ch->recoverycmd = 1; /* Find some holden command. */ for (i = 0; i < ch->numslots; i++) { if (ch->hold[i]) @@ -2081,26 +2094,45 @@ ahci_issue_read_log(device_t dev) 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_AHCI, 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_AHCI, 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; - /* Freeze SIM while doing READ LOG EXT. */ + /* Freeze SIM while doing recovery. */ xpt_freeze_simq(ch->sim, 1); ahci_begin_transaction(dev, ccb); } @@ -2113,7 +2145,7 @@ ahci_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 && @@ -2121,6 +2153,8 @@ ahci_process_read_log(device_t dev, unio for (i = 0; i < ch->numslots; i++) { if (!ch->hold[i]) continue; + if (ch->hold[i]->ccb_h.func_code != XPT_ATA_IO) + continue; if ((data[0] & 0x1F) == i) { res = &ch->hold[i]->ataio.res; res->status = data[2]; @@ -2151,6 +2185,8 @@ ahci_process_read_log(device_t dev, unio for (i = 0; i < ch->numslots; i++) { if (!ch->hold[i]) continue; + if (ch->hold[i]->ccb_h.func_code != XPT_ATA_IO) + continue; xpt_done(ch->hold[i]); ch->hold[i] = NULL; ch->numhslots--; @@ -2162,6 +2198,28 @@ ahci_process_read_log(device_t dev, unio } static void +ahci_process_request_sense(device_t dev, union ccb *ccb) +{ + struct ahci_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); + xpt_release_simq(ch->sim, TRUE); +} + +static void ahci_start(device_t dev, int fbs) { struct ahci_channel *ch = device_get_softc(dev); @@ -2519,6 +2577,7 @@ ahciaction(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 (ahci_check_collision(dev, ccb)) { /* Freeze command. */ Modified: head/sys/dev/ahci/ahci.h ============================================================================== --- head/sys/dev/ahci/ahci.h Tue Apr 12 11:17:46 2011 (r220564) +++ head/sys/dev/ahci/ahci.h Tue Apr 12 11:24:59 2011 (r220565) @@ -408,7 +408,7 @@ struct ahci_channel { int numtslots; /* Number of tagged slots */ int numtslotspd[16];/* Number of tagged slots per dev */ int numhslots; /* Number of holden slots */ - int readlog; /* Our READ LOG active */ + int recoverycmd; /* Our READ LOG active */ int fatalerr; /* Fatal error happend */ int lastslot; /* Last used slot */ int taggedtarget; /* Last tagged target */