1338ec570SDarrick J. Wong /* 2338ec570SDarrick J. Wong * Support for SATA devices on Serial Attached SCSI (SAS) controllers 3338ec570SDarrick J. Wong * 4338ec570SDarrick J. Wong * Copyright (C) 2006 IBM Corporation 5338ec570SDarrick J. Wong * 6338ec570SDarrick J. Wong * Written by: Darrick J. Wong <djwong@us.ibm.com>, IBM Corporation 7338ec570SDarrick J. Wong * 8338ec570SDarrick J. Wong * This program is free software; you can redistribute it and/or 9338ec570SDarrick J. Wong * modify it under the terms of the GNU General Public License as 10338ec570SDarrick J. Wong * published by the Free Software Foundation; either version 2 of the 11338ec570SDarrick J. Wong * License, or (at your option) any later version. 12338ec570SDarrick J. Wong * 13338ec570SDarrick J. Wong * This program is distributed in the hope that it will be useful, but 14338ec570SDarrick J. Wong * WITHOUT ANY WARRANTY; without even the implied warranty of 15338ec570SDarrick J. Wong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16338ec570SDarrick J. Wong * General Public License for more details. 17338ec570SDarrick J. Wong * 18338ec570SDarrick J. Wong * You should have received a copy of the GNU General Public License 19338ec570SDarrick J. Wong * along with this program; if not, write to the Free Software 20338ec570SDarrick J. Wong * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 21338ec570SDarrick J. Wong * USA 22338ec570SDarrick J. Wong */ 23338ec570SDarrick J. Wong 24b9142174SJames Bottomley #include <linux/scatterlist.h> 255a0e3ad6STejun Heo #include <linux/slab.h> 26*50824d6cSDan Williams #include <linux/async.h> 27b9142174SJames Bottomley 28338ec570SDarrick J. Wong #include <scsi/sas_ata.h> 29338ec570SDarrick J. Wong #include "sas_internal.h" 30338ec570SDarrick J. Wong #include <scsi/scsi_host.h> 31338ec570SDarrick J. Wong #include <scsi/scsi_device.h> 32338ec570SDarrick J. Wong #include <scsi/scsi_tcq.h> 33338ec570SDarrick J. Wong #include <scsi/scsi.h> 34338ec570SDarrick J. Wong #include <scsi/scsi_transport.h> 35338ec570SDarrick J. Wong #include <scsi/scsi_transport_sas.h> 36338ec570SDarrick J. Wong #include "../scsi_sas_internal.h" 373a2755afSDarrick J. Wong #include "../scsi_transport_api.h" 383a2755afSDarrick J. Wong #include <scsi/scsi_eh.h> 39338ec570SDarrick J. Wong 40338ec570SDarrick J. Wong static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts) 41338ec570SDarrick J. Wong { 42338ec570SDarrick J. Wong /* Cheesy attempt to translate SAS errors into ATA. Hah! */ 43338ec570SDarrick J. Wong 44338ec570SDarrick J. Wong /* transport error */ 45338ec570SDarrick J. Wong if (ts->resp == SAS_TASK_UNDELIVERED) 46338ec570SDarrick J. Wong return AC_ERR_ATA_BUS; 47338ec570SDarrick J. Wong 48338ec570SDarrick J. Wong /* ts->resp == SAS_TASK_COMPLETE */ 49338ec570SDarrick J. Wong /* task delivered, what happened afterwards? */ 50338ec570SDarrick J. Wong switch (ts->stat) { 51338ec570SDarrick J. Wong case SAS_DEV_NO_RESPONSE: 52338ec570SDarrick J. Wong return AC_ERR_TIMEOUT; 53338ec570SDarrick J. Wong 54338ec570SDarrick J. Wong case SAS_INTERRUPTED: 55338ec570SDarrick J. Wong case SAS_PHY_DOWN: 56338ec570SDarrick J. Wong case SAS_NAK_R_ERR: 57338ec570SDarrick J. Wong return AC_ERR_ATA_BUS; 58338ec570SDarrick J. Wong 59338ec570SDarrick J. Wong 60338ec570SDarrick J. Wong case SAS_DATA_UNDERRUN: 61338ec570SDarrick J. Wong /* 62338ec570SDarrick J. Wong * Some programs that use the taskfile interface 63338ec570SDarrick J. Wong * (smartctl in particular) can cause underrun 64338ec570SDarrick J. Wong * problems. Ignore these errors, perhaps at our 65338ec570SDarrick J. Wong * peril. 66338ec570SDarrick J. Wong */ 67338ec570SDarrick J. Wong return 0; 68338ec570SDarrick J. Wong 69338ec570SDarrick J. Wong case SAS_DATA_OVERRUN: 70338ec570SDarrick J. Wong case SAS_QUEUE_FULL: 71338ec570SDarrick J. Wong case SAS_DEVICE_UNKNOWN: 72338ec570SDarrick J. Wong case SAS_SG_ERR: 73338ec570SDarrick J. Wong return AC_ERR_INVALID; 74338ec570SDarrick J. Wong 75338ec570SDarrick J. Wong case SAS_OPEN_TO: 76338ec570SDarrick J. Wong case SAS_OPEN_REJECT: 77338ec570SDarrick J. Wong SAS_DPRINTK("%s: Saw error %d. What to do?\n", 78cadbd4a5SHarvey Harrison __func__, ts->stat); 79338ec570SDarrick J. Wong return AC_ERR_OTHER; 80338ec570SDarrick J. Wong 8175c0b386SJames Bottomley case SAM_STAT_CHECK_CONDITION: 82338ec570SDarrick J. Wong case SAS_ABORTED_TASK: 83338ec570SDarrick J. Wong return AC_ERR_DEV; 84338ec570SDarrick J. Wong 85338ec570SDarrick J. Wong case SAS_PROTO_RESPONSE: 86338ec570SDarrick J. Wong /* This means the ending_fis has the error 87338ec570SDarrick J. Wong * value; return 0 here to collect it */ 88338ec570SDarrick J. Wong return 0; 89338ec570SDarrick J. Wong default: 90338ec570SDarrick J. Wong return 0; 91338ec570SDarrick J. Wong } 92338ec570SDarrick J. Wong } 93338ec570SDarrick J. Wong 94338ec570SDarrick J. Wong static void sas_ata_task_done(struct sas_task *task) 95338ec570SDarrick J. Wong { 96338ec570SDarrick J. Wong struct ata_queued_cmd *qc = task->uldd_task; 979095a64aSDan Williams struct domain_device *dev = task->dev; 98338ec570SDarrick J. Wong struct task_status_struct *stat = &task->task_status; 99338ec570SDarrick J. Wong struct ata_task_resp *resp = (struct ata_task_resp *)stat->buf; 1009095a64aSDan Williams struct sas_ha_struct *sas_ha = dev->port->ha; 101338ec570SDarrick J. Wong enum ata_completion_errors ac; 1023eb7a51aSDarrick J. Wong unsigned long flags; 103bb650a1bSXiangliang Yu struct ata_link *link; 1043dff5721SDan Williams struct ata_port *ap; 105338ec570SDarrick J. Wong 1069095a64aSDan Williams spin_lock_irqsave(&dev->done_lock, flags); 1079095a64aSDan Williams if (test_bit(SAS_HA_FROZEN, &sas_ha->state)) 1089095a64aSDan Williams task = NULL; 1099095a64aSDan Williams else if (qc && qc->scsicmd) 1109095a64aSDan Williams ASSIGN_SAS_TASK(qc->scsicmd, NULL); 1119095a64aSDan Williams spin_unlock_irqrestore(&dev->done_lock, flags); 1129095a64aSDan Williams 1139095a64aSDan Williams /* check if libsas-eh got to the task before us */ 1149095a64aSDan Williams if (unlikely(!task)) 1159095a64aSDan Williams return; 1169095a64aSDan Williams 1171c50dc83SDarrick J. Wong if (!qc) 1181c50dc83SDarrick J. Wong goto qc_already_gone; 1191c50dc83SDarrick J. Wong 1203dff5721SDan Williams ap = qc->ap; 1213dff5721SDan Williams link = &ap->link; 1221c50dc83SDarrick J. Wong 1233dff5721SDan Williams spin_lock_irqsave(ap->lock, flags); 1243dff5721SDan Williams /* check if we lost the race with libata/sas_ata_post_internal() */ 1253dff5721SDan Williams if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) { 1263dff5721SDan Williams spin_unlock_irqrestore(ap->lock, flags); 1273dff5721SDan Williams if (qc->scsicmd) 1283dff5721SDan Williams goto qc_already_gone; 1293dff5721SDan Williams else { 1303dff5721SDan Williams /* if eh is not involved and the port is frozen then the 1313dff5721SDan Williams * ata internal abort process has taken responsibility 1323dff5721SDan Williams * for this sas_task 1333dff5721SDan Williams */ 1343dff5721SDan Williams return; 1353dff5721SDan Williams } 1363dff5721SDan Williams } 1373dff5721SDan Williams 13875c0b386SJames Bottomley if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || 13975c0b386SJames Bottomley ((stat->stat == SAM_STAT_CHECK_CONDITION && 14075c0b386SJames Bottomley dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { 141338ec570SDarrick J. Wong ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); 142bb650a1bSXiangliang Yu 143bb650a1bSXiangliang Yu if (!link->sactive) { 144338ec570SDarrick J. Wong qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); 145bb650a1bSXiangliang Yu } else { 146bb650a1bSXiangliang Yu link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command); 147bb650a1bSXiangliang Yu if (unlikely(link->eh_info.err_mask)) 148bb650a1bSXiangliang Yu qc->flags |= ATA_QCFLAG_FAILED; 149bb650a1bSXiangliang Yu } 15075c0b386SJames Bottomley } else { 151338ec570SDarrick J. Wong ac = sas_to_ata_err(stat); 152338ec570SDarrick J. Wong if (ac) { 153cadbd4a5SHarvey Harrison SAS_DPRINTK("%s: SAS error %x\n", __func__, 154338ec570SDarrick J. Wong stat->stat); 155338ec570SDarrick J. Wong /* We saw a SAS error. Send a vague error. */ 156bb650a1bSXiangliang Yu if (!link->sactive) { 157338ec570SDarrick J. Wong qc->err_mask = ac; 158bb650a1bSXiangliang Yu } else { 159bb650a1bSXiangliang Yu link->eh_info.err_mask |= AC_ERR_DEV; 160bb650a1bSXiangliang Yu qc->flags |= ATA_QCFLAG_FAILED; 161bb650a1bSXiangliang Yu } 162bb650a1bSXiangliang Yu 163338ec570SDarrick J. Wong dev->sata_dev.tf.feature = 0x04; /* status err */ 164338ec570SDarrick J. Wong dev->sata_dev.tf.command = ATA_ERR; 165338ec570SDarrick J. Wong } 166338ec570SDarrick J. Wong } 167338ec570SDarrick J. Wong 1681c50dc83SDarrick J. Wong qc->lldd_task = NULL; 169338ec570SDarrick J. Wong ata_qc_complete(qc); 1703dff5721SDan Williams spin_unlock_irqrestore(ap->lock, flags); 1713eb7a51aSDarrick J. Wong 1721c50dc83SDarrick J. Wong qc_already_gone: 173338ec570SDarrick J. Wong list_del_init(&task->list); 174338ec570SDarrick J. Wong sas_free_task(task); 175338ec570SDarrick J. Wong } 176338ec570SDarrick J. Wong 177338ec570SDarrick J. Wong static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) 178338ec570SDarrick J. Wong { 179312d3e56SDan Williams unsigned long flags; 180338ec570SDarrick J. Wong struct sas_task *task; 181312d3e56SDan Williams struct scatterlist *sg; 182312d3e56SDan Williams int ret = AC_ERR_SYSTEM; 183312d3e56SDan Williams unsigned int si, xfer = 0; 184312d3e56SDan Williams struct ata_port *ap = qc->ap; 185312d3e56SDan Williams struct domain_device *dev = ap->private_data; 186338ec570SDarrick J. Wong struct sas_ha_struct *sas_ha = dev->port->ha; 187338ec570SDarrick J. Wong struct Scsi_Host *host = sas_ha->core.shost; 188338ec570SDarrick J. Wong struct sas_internal *i = to_sas_internal(host->transportt); 189312d3e56SDan Williams 190312d3e56SDan Williams /* TODO: audit callers to ensure they are ready for qc_issue to 191312d3e56SDan Williams * unconditionally re-enable interrupts 192312d3e56SDan Williams */ 193312d3e56SDan Williams local_irq_save(flags); 194312d3e56SDan Williams spin_unlock(ap->lock); 195338ec570SDarrick J. Wong 19656dd2c06SDarrick J. Wong /* If the device fell off, no sense in issuing commands */ 197e139942dSDan Williams if (test_bit(SAS_DEV_GONE, &dev->state)) 198312d3e56SDan Williams goto out; 19956dd2c06SDarrick J. Wong 200338ec570SDarrick J. Wong task = sas_alloc_task(GFP_ATOMIC); 201338ec570SDarrick J. Wong if (!task) 202312d3e56SDan Williams goto out; 203338ec570SDarrick J. Wong task->dev = dev; 204338ec570SDarrick J. Wong task->task_proto = SAS_PROTOCOL_STP; 205338ec570SDarrick J. Wong task->task_done = sas_ata_task_done; 206338ec570SDarrick J. Wong 207338ec570SDarrick J. Wong if (qc->tf.command == ATA_CMD_FPDMA_WRITE || 208338ec570SDarrick J. Wong qc->tf.command == ATA_CMD_FPDMA_READ) { 209338ec570SDarrick J. Wong /* Need to zero out the tag libata assigned us */ 210338ec570SDarrick J. Wong qc->tf.nsect = 0; 211338ec570SDarrick J. Wong } 212338ec570SDarrick J. Wong 213110dd8f1SJames Bottomley ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); 214338ec570SDarrick J. Wong task->uldd_task = qc; 215405e66b3STejun Heo if (ata_is_atapi(qc->tf.protocol)) { 216338ec570SDarrick J. Wong memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); 217dde20207SJames Bottomley task->total_xfer_len = qc->nbytes; 218dde20207SJames Bottomley task->num_scatter = qc->n_elem; 219338ec570SDarrick J. Wong } else { 220ff2aeb1eSTejun Heo for_each_sg(qc->sg, sg, qc->n_elem, si) 221338ec570SDarrick J. Wong xfer += sg->length; 222338ec570SDarrick J. Wong 223338ec570SDarrick J. Wong task->total_xfer_len = xfer; 224ff2aeb1eSTejun Heo task->num_scatter = si; 225338ec570SDarrick J. Wong } 226338ec570SDarrick J. Wong 227338ec570SDarrick J. Wong task->data_dir = qc->dma_dir; 228ff2aeb1eSTejun Heo task->scatter = qc->sg; 229338ec570SDarrick J. Wong task->ata_task.retry_count = 1; 230338ec570SDarrick J. Wong task->task_state_flags = SAS_TASK_STATE_PENDING; 2311c50dc83SDarrick J. Wong qc->lldd_task = task; 232338ec570SDarrick J. Wong 233338ec570SDarrick J. Wong switch (qc->tf.protocol) { 234338ec570SDarrick J. Wong case ATA_PROT_NCQ: 235338ec570SDarrick J. Wong task->ata_task.use_ncq = 1; 236338ec570SDarrick J. Wong /* fall through */ 2370dc36888STejun Heo case ATAPI_PROT_DMA: 238338ec570SDarrick J. Wong case ATA_PROT_DMA: 239338ec570SDarrick J. Wong task->ata_task.dma_xfer = 1; 240338ec570SDarrick J. Wong break; 241338ec570SDarrick J. Wong } 242338ec570SDarrick J. Wong 243fe059f12SDarrick J. Wong if (qc->scsicmd) 244fe059f12SDarrick J. Wong ASSIGN_SAS_TASK(qc->scsicmd, task); 245fe059f12SDarrick J. Wong 246338ec570SDarrick J. Wong if (sas_ha->lldd_max_execute_num < 2) 247312d3e56SDan Williams ret = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC); 248338ec570SDarrick J. Wong else 249312d3e56SDan Williams ret = sas_queue_up(task); 250338ec570SDarrick J. Wong 251338ec570SDarrick J. Wong /* Examine */ 252312d3e56SDan Williams if (ret) { 253312d3e56SDan Williams SAS_DPRINTK("lldd_execute_task returned: %d\n", ret); 254338ec570SDarrick J. Wong 255fe059f12SDarrick J. Wong if (qc->scsicmd) 256fe059f12SDarrick J. Wong ASSIGN_SAS_TASK(qc->scsicmd, NULL); 257338ec570SDarrick J. Wong sas_free_task(task); 258312d3e56SDan Williams ret = AC_ERR_SYSTEM; 259338ec570SDarrick J. Wong } 260338ec570SDarrick J. Wong 261312d3e56SDan Williams out: 262312d3e56SDan Williams spin_lock(ap->lock); 263312d3e56SDan Williams local_irq_restore(flags); 264312d3e56SDan Williams return ret; 265338ec570SDarrick J. Wong } 266338ec570SDarrick J. Wong 2674c9bf4e7STejun Heo static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) 2684c9bf4e7STejun Heo { 2694c9bf4e7STejun Heo struct domain_device *dev = qc->ap->private_data; 2704c9bf4e7STejun Heo 2714c9bf4e7STejun Heo memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf)); 2724c9bf4e7STejun Heo return true; 2734c9bf4e7STejun Heo } 2744c9bf4e7STejun Heo 27500dd4998SJames Bottomley static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, 27600dd4998SJames Bottomley unsigned long deadline) 277338ec570SDarrick J. Wong { 27800dd4998SJames Bottomley struct ata_port *ap = link->ap; 279338ec570SDarrick J. Wong struct domain_device *dev = ap->private_data; 280338ec570SDarrick J. Wong struct sas_internal *i = 281338ec570SDarrick J. Wong to_sas_internal(dev->port->ha->core.shost->transportt); 282a29c0515SJames Bottomley int res = TMF_RESP_FUNC_FAILED; 28300dd4998SJames Bottomley int ret = 0; 284338ec570SDarrick J. Wong 285338ec570SDarrick J. Wong if (i->dft->lldd_I_T_nexus_reset) 286338ec570SDarrick J. Wong res = i->dft->lldd_I_T_nexus_reset(dev); 287338ec570SDarrick J. Wong 28800dd4998SJames Bottomley if (res != TMF_RESP_FUNC_COMPLETE) { 289cadbd4a5SHarvey Harrison SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__); 29000dd4998SJames Bottomley ret = -EAGAIN; 29100dd4998SJames Bottomley } 292338ec570SDarrick J. Wong 293338ec570SDarrick J. Wong switch (dev->sata_dev.command_set) { 294338ec570SDarrick J. Wong case ATA_COMMAND_SET: 295cadbd4a5SHarvey Harrison SAS_DPRINTK("%s: Found ATA device.\n", __func__); 29600dd4998SJames Bottomley *class = ATA_DEV_ATA; 297338ec570SDarrick J. Wong break; 298338ec570SDarrick J. Wong case ATAPI_COMMAND_SET: 299cadbd4a5SHarvey Harrison SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); 30000dd4998SJames Bottomley *class = ATA_DEV_ATAPI; 301338ec570SDarrick J. Wong break; 302338ec570SDarrick J. Wong default: 303338ec570SDarrick J. Wong SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", 304cadbd4a5SHarvey Harrison __func__, 305338ec570SDarrick J. Wong dev->sata_dev.command_set); 30600dd4998SJames Bottomley *class = ATA_DEV_UNKNOWN; 307338ec570SDarrick J. Wong break; 308338ec570SDarrick J. Wong } 309338ec570SDarrick J. Wong 310338ec570SDarrick J. Wong ap->cbl = ATA_CBL_SATA; 31100dd4998SJames Bottomley return ret; 312338ec570SDarrick J. Wong } 313338ec570SDarrick J. Wong 3141ca1e43eSDave Jiang static int sas_ata_soft_reset(struct ata_link *link, unsigned int *class, 3151ca1e43eSDave Jiang unsigned long deadline) 3161ca1e43eSDave Jiang { 3171ca1e43eSDave Jiang struct ata_port *ap = link->ap; 3181ca1e43eSDave Jiang struct domain_device *dev = ap->private_data; 3191ca1e43eSDave Jiang struct sas_internal *i = 3201ca1e43eSDave Jiang to_sas_internal(dev->port->ha->core.shost->transportt); 3211ca1e43eSDave Jiang int res = TMF_RESP_FUNC_FAILED; 3221ca1e43eSDave Jiang int ret = 0; 3231ca1e43eSDave Jiang 3241ca1e43eSDave Jiang if (i->dft->lldd_ata_soft_reset) 3251ca1e43eSDave Jiang res = i->dft->lldd_ata_soft_reset(dev); 3261ca1e43eSDave Jiang 3271ca1e43eSDave Jiang if (res != TMF_RESP_FUNC_COMPLETE) { 3281ca1e43eSDave Jiang SAS_DPRINTK("%s: Unable to soft reset\n", __func__); 3291ca1e43eSDave Jiang ret = -EAGAIN; 3301ca1e43eSDave Jiang } 3311ca1e43eSDave Jiang 3321ca1e43eSDave Jiang switch (dev->sata_dev.command_set) { 3331ca1e43eSDave Jiang case ATA_COMMAND_SET: 3341ca1e43eSDave Jiang SAS_DPRINTK("%s: Found ATA device.\n", __func__); 3351ca1e43eSDave Jiang *class = ATA_DEV_ATA; 3361ca1e43eSDave Jiang break; 3371ca1e43eSDave Jiang case ATAPI_COMMAND_SET: 3381ca1e43eSDave Jiang SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); 3391ca1e43eSDave Jiang *class = ATA_DEV_ATAPI; 3401ca1e43eSDave Jiang break; 3411ca1e43eSDave Jiang default: 3421ca1e43eSDave Jiang SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", 3431ca1e43eSDave Jiang __func__, dev->sata_dev.command_set); 3441ca1e43eSDave Jiang *class = ATA_DEV_UNKNOWN; 3451ca1e43eSDave Jiang break; 3461ca1e43eSDave Jiang } 3471ca1e43eSDave Jiang 3481ca1e43eSDave Jiang ap->cbl = ATA_CBL_SATA; 3491ca1e43eSDave Jiang return ret; 3501ca1e43eSDave Jiang } 3511ca1e43eSDave Jiang 3523dff5721SDan Williams /* 3533dff5721SDan Williams * notify the lldd to forget the sas_task for this internal ata command 3543dff5721SDan Williams * that bypasses scsi-eh 3553dff5721SDan Williams */ 3563dff5721SDan Williams static void sas_ata_internal_abort(struct sas_task *task) 3573dff5721SDan Williams { 3583dff5721SDan Williams struct sas_internal *si = 3593dff5721SDan Williams to_sas_internal(task->dev->port->ha->core.shost->transportt); 3603dff5721SDan Williams unsigned long flags; 3613dff5721SDan Williams int res; 3623dff5721SDan Williams 3633dff5721SDan Williams spin_lock_irqsave(&task->task_state_lock, flags); 3643dff5721SDan Williams if (task->task_state_flags & SAS_TASK_STATE_ABORTED || 3653dff5721SDan Williams task->task_state_flags & SAS_TASK_STATE_DONE) { 3663dff5721SDan Williams spin_unlock_irqrestore(&task->task_state_lock, flags); 3673dff5721SDan Williams SAS_DPRINTK("%s: Task %p already finished.\n", __func__, 3683dff5721SDan Williams task); 3693dff5721SDan Williams goto out; 3703dff5721SDan Williams } 3713dff5721SDan Williams task->task_state_flags |= SAS_TASK_STATE_ABORTED; 3723dff5721SDan Williams spin_unlock_irqrestore(&task->task_state_lock, flags); 3733dff5721SDan Williams 3743dff5721SDan Williams res = si->dft->lldd_abort_task(task); 3753dff5721SDan Williams 3763dff5721SDan Williams spin_lock_irqsave(&task->task_state_lock, flags); 3773dff5721SDan Williams if (task->task_state_flags & SAS_TASK_STATE_DONE || 3783dff5721SDan Williams res == TMF_RESP_FUNC_COMPLETE) { 3793dff5721SDan Williams spin_unlock_irqrestore(&task->task_state_lock, flags); 3803dff5721SDan Williams goto out; 3813dff5721SDan Williams } 3823dff5721SDan Williams 3833dff5721SDan Williams /* XXX we are not prepared to deal with ->lldd_abort_task() 3843dff5721SDan Williams * failures. TODO: lldds need to unconditionally forget about 3853dff5721SDan Williams * aborted ata tasks, otherwise we (likely) leak the sas task 3863dff5721SDan Williams * here 3873dff5721SDan Williams */ 3883dff5721SDan Williams SAS_DPRINTK("%s: Task %p leaked.\n", __func__, task); 3893dff5721SDan Williams 3903dff5721SDan Williams if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) 3913dff5721SDan Williams task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; 3923dff5721SDan Williams spin_unlock_irqrestore(&task->task_state_lock, flags); 3933dff5721SDan Williams 3943dff5721SDan Williams return; 3953dff5721SDan Williams out: 3963dff5721SDan Williams list_del_init(&task->list); 3973dff5721SDan Williams sas_free_task(task); 3983dff5721SDan Williams } 3993dff5721SDan Williams 400338ec570SDarrick J. Wong static void sas_ata_post_internal(struct ata_queued_cmd *qc) 401338ec570SDarrick J. Wong { 402338ec570SDarrick J. Wong if (qc->flags & ATA_QCFLAG_FAILED) 403338ec570SDarrick J. Wong qc->err_mask |= AC_ERR_OTHER; 404338ec570SDarrick J. Wong 4051c50dc83SDarrick J. Wong if (qc->err_mask) { 4061c50dc83SDarrick J. Wong /* 4073dff5721SDan Williams * Find the sas_task and kill it. By this point, libata 4083dff5721SDan Williams * has decided to kill the qc and has frozen the port. 4093dff5721SDan Williams * In this state sas_ata_task_done() will no longer free 4103dff5721SDan Williams * the sas_task, so we need to notify the lldd (via 4113dff5721SDan Williams * ->lldd_abort_task) that the task is dead and free it 4123dff5721SDan Williams * ourselves. 4131c50dc83SDarrick J. Wong */ 4141c50dc83SDarrick J. Wong struct sas_task *task = qc->lldd_task; 4151c50dc83SDarrick J. Wong 4161c50dc83SDarrick J. Wong qc->lldd_task = NULL; 4173a2cdf39SDan Williams if (!task) 4183a2cdf39SDan Williams return; 4191c50dc83SDarrick J. Wong task->uldd_task = NULL; 4203dff5721SDan Williams sas_ata_internal_abort(task); 4211c50dc83SDarrick J. Wong } 4221c50dc83SDarrick J. Wong } 423338ec570SDarrick J. Wong 424b91bb296SDan Williams 425b91bb296SDan Williams static void sas_ata_set_dmamode(struct ata_port *ap, struct ata_device *ata_dev) 426b91bb296SDan Williams { 427b91bb296SDan Williams struct domain_device *dev = ap->private_data; 428b91bb296SDan Williams struct sas_internal *i = 429b91bb296SDan Williams to_sas_internal(dev->port->ha->core.shost->transportt); 430b91bb296SDan Williams 431b91bb296SDan Williams if (i->dft->lldd_ata_set_dmamode) 432b91bb296SDan Williams i->dft->lldd_ata_set_dmamode(dev); 433b91bb296SDan Williams } 434b91bb296SDan Williams 435338ec570SDarrick J. Wong static struct ata_port_operations sas_sata_ops = { 43600dd4998SJames Bottomley .prereset = ata_std_prereset, 4371ca1e43eSDave Jiang .softreset = sas_ata_soft_reset, 43800dd4998SJames Bottomley .hardreset = sas_ata_hard_reset, 43900dd4998SJames Bottomley .postreset = ata_std_postreset, 44000dd4998SJames Bottomley .error_handler = ata_std_error_handler, 441338ec570SDarrick J. Wong .post_internal_cmd = sas_ata_post_internal, 442f0ad30d3SDavid Milburn .qc_defer = ata_std_qc_defer, 443338ec570SDarrick J. Wong .qc_prep = ata_noop_qc_prep, 444338ec570SDarrick J. Wong .qc_issue = sas_ata_qc_issue, 4454c9bf4e7STejun Heo .qc_fill_rtf = sas_ata_qc_fill_rtf, 446338ec570SDarrick J. Wong .port_start = ata_sas_port_start, 447338ec570SDarrick J. Wong .port_stop = ata_sas_port_stop, 448b91bb296SDan Williams .set_dmamode = sas_ata_set_dmamode, 449338ec570SDarrick J. Wong }; 450338ec570SDarrick J. Wong 451338ec570SDarrick J. Wong static struct ata_port_info sata_port_info = { 4529cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ, 4530f2e0330SSergei Shtylyov .pio_mask = ATA_PIO4, 4540f2e0330SSergei Shtylyov .mwdma_mask = ATA_MWDMA2, 455338ec570SDarrick J. Wong .udma_mask = ATA_UDMA6, 456338ec570SDarrick J. Wong .port_ops = &sas_sata_ops 457338ec570SDarrick J. Wong }; 458338ec570SDarrick J. Wong 459338ec570SDarrick J. Wong int sas_ata_init_host_and_port(struct domain_device *found_dev, 460338ec570SDarrick J. Wong struct scsi_target *starget) 461338ec570SDarrick J. Wong { 462338ec570SDarrick J. Wong struct Scsi_Host *shost = dev_to_shost(&starget->dev); 463338ec570SDarrick J. Wong struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); 464338ec570SDarrick J. Wong struct ata_port *ap; 465338ec570SDarrick J. Wong 466338ec570SDarrick J. Wong ata_host_init(&found_dev->sata_dev.ata_host, 4671d1bbee6SJeff Garzik ha->dev, 468338ec570SDarrick J. Wong sata_port_info.flags, 469338ec570SDarrick J. Wong &sas_sata_ops); 470338ec570SDarrick J. Wong ap = ata_sas_port_alloc(&found_dev->sata_dev.ata_host, 471338ec570SDarrick J. Wong &sata_port_info, 472338ec570SDarrick J. Wong shost); 473338ec570SDarrick J. Wong if (!ap) { 474338ec570SDarrick J. Wong SAS_DPRINTK("ata_sas_port_alloc failed.\n"); 475338ec570SDarrick J. Wong return -ENODEV; 476338ec570SDarrick J. Wong } 477338ec570SDarrick J. Wong 478338ec570SDarrick J. Wong ap->private_data = found_dev; 479338ec570SDarrick J. Wong ap->cbl = ATA_CBL_SATA; 480338ec570SDarrick J. Wong ap->scsi_host = shost; 481338ec570SDarrick J. Wong found_dev->sata_dev.ap = ap; 482338ec570SDarrick J. Wong 483338ec570SDarrick J. Wong return 0; 484338ec570SDarrick J. Wong } 4853a2755afSDarrick J. Wong 4863a2755afSDarrick J. Wong void sas_ata_task_abort(struct sas_task *task) 4873a2755afSDarrick J. Wong { 4883a2755afSDarrick J. Wong struct ata_queued_cmd *qc = task->uldd_task; 4893a2755afSDarrick J. Wong struct completion *waiting; 4903a2755afSDarrick J. Wong 4913a2755afSDarrick J. Wong /* Bounce SCSI-initiated commands to the SCSI EH */ 4923a2755afSDarrick J. Wong if (qc->scsicmd) { 4931b4d0d8eSJames Bottomley struct request_queue *q = qc->scsicmd->device->request_queue; 4941b4d0d8eSJames Bottomley unsigned long flags; 4951b4d0d8eSJames Bottomley 49670b25f89STejun Heo spin_lock_irqsave(q->queue_lock, flags); 497242f9dcbSJens Axboe blk_abort_request(qc->scsicmd->request); 49870b25f89STejun Heo spin_unlock_irqrestore(q->queue_lock, flags); 4993a2755afSDarrick J. Wong scsi_schedule_eh(qc->scsicmd->device->host); 5003a2755afSDarrick J. Wong return; 5013a2755afSDarrick J. Wong } 5023a2755afSDarrick J. Wong 5033a2755afSDarrick J. Wong /* Internal command, fake a timeout and complete. */ 5043a2755afSDarrick J. Wong qc->flags &= ~ATA_QCFLAG_ACTIVE; 5053a2755afSDarrick J. Wong qc->flags |= ATA_QCFLAG_FAILED; 5063a2755afSDarrick J. Wong qc->err_mask |= AC_ERR_TIMEOUT; 5073a2755afSDarrick J. Wong waiting = qc->private_data; 5083a2755afSDarrick J. Wong complete(waiting); 5093a2755afSDarrick J. Wong } 510b9142174SJames Bottomley 511b9142174SJames Bottomley static void sas_get_ata_command_set(struct domain_device *dev) 512b9142174SJames Bottomley { 513b9142174SJames Bottomley struct dev_to_host_fis *fis = 514b9142174SJames Bottomley (struct dev_to_host_fis *) dev->frame_rcvd; 515b9142174SJames Bottomley 516b9142174SJames Bottomley if ((fis->sector_count == 1 && /* ATA */ 517b9142174SJames Bottomley fis->lbal == 1 && 518b9142174SJames Bottomley fis->lbam == 0 && 519b9142174SJames Bottomley fis->lbah == 0 && 520b9142174SJames Bottomley fis->device == 0) 521b9142174SJames Bottomley || 522b9142174SJames Bottomley (fis->sector_count == 0 && /* CE-ATA (mATA) */ 523b9142174SJames Bottomley fis->lbal == 0 && 524b9142174SJames Bottomley fis->lbam == 0xCE && 525b9142174SJames Bottomley fis->lbah == 0xAA && 526b9142174SJames Bottomley (fis->device & ~0x10) == 0)) 527b9142174SJames Bottomley 528b9142174SJames Bottomley dev->sata_dev.command_set = ATA_COMMAND_SET; 529b9142174SJames Bottomley 530b9142174SJames Bottomley else if ((fis->interrupt_reason == 1 && /* ATAPI */ 531b9142174SJames Bottomley fis->lbal == 1 && 532b9142174SJames Bottomley fis->byte_count_low == 0x14 && 533b9142174SJames Bottomley fis->byte_count_high == 0xEB && 534b9142174SJames Bottomley (fis->device & ~0x10) == 0)) 535b9142174SJames Bottomley 536b9142174SJames Bottomley dev->sata_dev.command_set = ATAPI_COMMAND_SET; 537b9142174SJames Bottomley 538b9142174SJames Bottomley else if ((fis->sector_count == 1 && /* SEMB */ 539b9142174SJames Bottomley fis->lbal == 1 && 540b9142174SJames Bottomley fis->lbam == 0x3C && 541b9142174SJames Bottomley fis->lbah == 0xC3 && 542b9142174SJames Bottomley fis->device == 0) 543b9142174SJames Bottomley || 544b9142174SJames Bottomley (fis->interrupt_reason == 1 && /* SATA PM */ 545b9142174SJames Bottomley fis->lbal == 1 && 546b9142174SJames Bottomley fis->byte_count_low == 0x69 && 547b9142174SJames Bottomley fis->byte_count_high == 0x96 && 548b9142174SJames Bottomley (fis->device & ~0x10) == 0)) 549b9142174SJames Bottomley 550b9142174SJames Bottomley /* Treat it as a superset? */ 551b9142174SJames Bottomley dev->sata_dev.command_set = ATAPI_COMMAND_SET; 552b9142174SJames Bottomley } 553b9142174SJames Bottomley 55487c8331fSDan Williams void sas_probe_sata(struct work_struct *work) 55587c8331fSDan Williams { 55687c8331fSDan Williams struct domain_device *dev, *n; 55787c8331fSDan Williams struct sas_discovery_event *ev = 55887c8331fSDan Williams container_of(work, struct sas_discovery_event, work); 55987c8331fSDan Williams struct asd_sas_port *port = ev->port; 56087c8331fSDan Williams 56187c8331fSDan Williams clear_bit(DISCE_PROBE, &port->disc.pending); 56287c8331fSDan Williams 56387c8331fSDan Williams list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) { 56487c8331fSDan Williams int err; 56587c8331fSDan Williams 56687c8331fSDan Williams spin_lock_irq(&port->dev_list_lock); 56787c8331fSDan Williams list_add_tail(&dev->dev_list_node, &port->dev_list); 56887c8331fSDan Williams spin_unlock_irq(&port->dev_list_lock); 56987c8331fSDan Williams 57087c8331fSDan Williams err = sas_rphy_add(dev->rphy); 57187c8331fSDan Williams 57287c8331fSDan Williams if (err) { 57387c8331fSDan Williams SAS_DPRINTK("%s: for %s device %16llx returned %d\n", 57487c8331fSDan Williams __func__, dev->parent ? "exp-attached" : 57587c8331fSDan Williams "direct-attached", 57687c8331fSDan Williams SAS_ADDR(dev->sas_addr), err); 57787c8331fSDan Williams sas_unregister_dev(port, dev); 57887c8331fSDan Williams } else 57987c8331fSDan Williams list_del_init(&dev->disco_list_node); 58087c8331fSDan Williams } 58187c8331fSDan Williams } 58287c8331fSDan Williams 583b9142174SJames Bottomley /** 584b9142174SJames Bottomley * sas_discover_sata -- discover an STP/SATA domain device 585b9142174SJames Bottomley * @dev: pointer to struct domain_device of interest 586b9142174SJames Bottomley * 587b91bb296SDan Williams * Devices directly attached to a HA port, have no parents. All other 588b91bb296SDan Williams * devices do, and should have their "parent" pointer set appropriately 589b91bb296SDan Williams * before calling this function. 590b9142174SJames Bottomley */ 591b9142174SJames Bottomley int sas_discover_sata(struct domain_device *dev) 592b9142174SJames Bottomley { 593b9142174SJames Bottomley int res; 594b9142174SJames Bottomley 595b91bb296SDan Williams if (dev->dev_type == SATA_PM) 596b91bb296SDan Williams return -ENODEV; 597b91bb296SDan Williams 598b9142174SJames Bottomley sas_get_ata_command_set(dev); 599b91bb296SDan Williams sas_fill_in_rphy(dev, dev->rphy); 60087c8331fSDan Williams 60187c8331fSDan Williams res = sas_notify_lldd_dev_found(dev); 60287c8331fSDan Williams if (res) 60387c8331fSDan Williams return res; 60487c8331fSDan Williams 60587c8331fSDan Williams sas_discover_event(dev->port, DISCE_PROBE); 606b91bb296SDan Williams return 0; 607b9142174SJames Bottomley } 60800dd4998SJames Bottomley 609*50824d6cSDan Williams static void async_sas_ata_eh(void *data, async_cookie_t cookie) 610*50824d6cSDan Williams { 611*50824d6cSDan Williams struct domain_device *dev = data; 612*50824d6cSDan Williams struct ata_port *ap = dev->sata_dev.ap; 613*50824d6cSDan Williams struct sas_ha_struct *ha = dev->port->ha; 614*50824d6cSDan Williams 615*50824d6cSDan Williams ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler"); 616*50824d6cSDan Williams ata_scsi_port_error_handler(ha->core.shost, ap); 617*50824d6cSDan Williams } 618*50824d6cSDan Williams 61900dd4998SJames Bottomley void sas_ata_strategy_handler(struct Scsi_Host *shost) 62000dd4998SJames Bottomley { 62100dd4998SJames Bottomley struct scsi_device *sdev; 62287c8331fSDan Williams struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); 623*50824d6cSDan Williams LIST_HEAD(async); 62487c8331fSDan Williams 62587c8331fSDan Williams /* it's ok to defer revalidation events during ata eh, these 62687c8331fSDan Williams * disks are in one of three states: 62787c8331fSDan Williams * 1/ present for initial domain discovery, and these 62887c8331fSDan Williams * resets will cause bcn flutters 62987c8331fSDan Williams * 2/ hot removed, we'll discover that after eh fails 63087c8331fSDan Williams * 3/ hot added after initial discovery, lost the race, and need 63187c8331fSDan Williams * to catch the next train. 63287c8331fSDan Williams */ 63387c8331fSDan Williams sas_disable_revalidation(sas_ha); 63400dd4998SJames Bottomley 63500dd4998SJames Bottomley shost_for_each_device(sdev, shost) { 63600dd4998SJames Bottomley struct domain_device *ddev = sdev_to_domain_dev(sdev); 63700dd4998SJames Bottomley 63800dd4998SJames Bottomley if (!dev_is_sata(ddev)) 63900dd4998SJames Bottomley continue; 64000dd4998SJames Bottomley 641*50824d6cSDan Williams async_schedule_domain(async_sas_ata_eh, ddev, &async); 64200dd4998SJames Bottomley } 643*50824d6cSDan Williams async_synchronize_full_domain(&async); 64487c8331fSDan Williams 64587c8331fSDan Williams sas_enable_revalidation(sas_ha); 64600dd4998SJames Bottomley } 64700dd4998SJames Bottomley 64800dd4998SJames Bottomley int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q, 64900dd4998SJames Bottomley struct list_head *done_q) 65000dd4998SJames Bottomley { 65100dd4998SJames Bottomley int rtn = 0; 65200dd4998SJames Bottomley struct scsi_cmnd *cmd, *n; 65300dd4998SJames Bottomley struct ata_port *ap; 65400dd4998SJames Bottomley 65500dd4998SJames Bottomley do { 65600dd4998SJames Bottomley LIST_HEAD(sata_q); 65700dd4998SJames Bottomley 65800dd4998SJames Bottomley ap = NULL; 65900dd4998SJames Bottomley 66000dd4998SJames Bottomley list_for_each_entry_safe(cmd, n, work_q, eh_entry) { 66100dd4998SJames Bottomley struct domain_device *ddev = cmd_to_domain_dev(cmd); 66200dd4998SJames Bottomley 66300dd4998SJames Bottomley if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd)) 66400dd4998SJames Bottomley continue; 66500dd4998SJames Bottomley if (ap && ap != ddev->sata_dev.ap) 66600dd4998SJames Bottomley continue; 66700dd4998SJames Bottomley ap = ddev->sata_dev.ap; 66800dd4998SJames Bottomley rtn = 1; 66900dd4998SJames Bottomley list_move(&cmd->eh_entry, &sata_q); 67000dd4998SJames Bottomley } 67100dd4998SJames Bottomley 67200dd4998SJames Bottomley if (!list_empty(&sata_q)) { 67300dd4998SJames Bottomley ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata cmd error handler\n"); 67400dd4998SJames Bottomley ata_scsi_cmd_error_handler(shost, ap, &sata_q); 675a82058a7SJames Bottomley /* 676a82058a7SJames Bottomley * ata's error handler may leave the cmd on the list 677a82058a7SJames Bottomley * so make sure they don't remain on a stack list 678a82058a7SJames Bottomley * about to go out of scope. 679a82058a7SJames Bottomley * 680a82058a7SJames Bottomley * This looks strange, since the commands are 681a82058a7SJames Bottomley * now part of no list, but the next error 682a82058a7SJames Bottomley * action will be ata_port_error_handler() 683a82058a7SJames Bottomley * which takes no list and sweeps them up 684a82058a7SJames Bottomley * anyway from the ata tag array. 685a82058a7SJames Bottomley */ 686a82058a7SJames Bottomley while (!list_empty(&sata_q)) 687a82058a7SJames Bottomley list_del_init(sata_q.next); 68800dd4998SJames Bottomley } 68900dd4998SJames Bottomley } while (ap); 69000dd4998SJames Bottomley 69100dd4998SJames Bottomley return rtn; 69200dd4998SJames Bottomley } 693b52df417SDan Williams 694b52df417SDan Williams void sas_ata_schedule_reset(struct domain_device *dev) 695b52df417SDan Williams { 696b52df417SDan Williams struct ata_eh_info *ehi; 697b52df417SDan Williams struct ata_port *ap; 698b52df417SDan Williams unsigned long flags; 699b52df417SDan Williams 700b52df417SDan Williams if (!dev_is_sata(dev)) 701b52df417SDan Williams return; 702b52df417SDan Williams 703b52df417SDan Williams ap = dev->sata_dev.ap; 704b52df417SDan Williams ehi = &ap->link.eh_info; 705b52df417SDan Williams 706b52df417SDan Williams spin_lock_irqsave(ap->lock, flags); 707b52df417SDan Williams ehi->err_mask |= AC_ERR_TIMEOUT; 708b52df417SDan Williams ehi->action |= ATA_EH_RESET; 709b52df417SDan Williams ata_port_schedule_eh(ap); 710b52df417SDan Williams spin_unlock_irqrestore(ap->lock, flags); 711b52df417SDan Williams } 71281c757bcSDan Williams 71381c757bcSDan Williams void sas_ata_wait_eh(struct domain_device *dev) 71481c757bcSDan Williams { 71581c757bcSDan Williams struct ata_port *ap; 71681c757bcSDan Williams 71781c757bcSDan Williams if (!dev_is_sata(dev)) 71881c757bcSDan Williams return; 71981c757bcSDan Williams 72081c757bcSDan Williams ap = dev->sata_dev.ap; 72181c757bcSDan Williams ata_port_wait_eh(ap); 72281c757bcSDan Williams } 723