diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
| -rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 80 | 
1 files changed, 22 insertions, 58 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 4d3b704ede1..31fc21f4d83 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -71,13 +71,13 @@ static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts)  		case SAS_SG_ERR:  			return AC_ERR_INVALID; -		case SAM_STAT_CHECK_CONDITION:  		case SAS_OPEN_TO:  		case SAS_OPEN_REJECT:  			SAS_DPRINTK("%s: Saw error %d.  What to do?\n",  				    __func__, ts->stat);  			return AC_ERR_OTHER; +		case SAM_STAT_CHECK_CONDITION:  		case SAS_ABORTED_TASK:  			return AC_ERR_DEV; @@ -107,13 +107,15 @@ static void sas_ata_task_done(struct sas_task *task)  	sas_ha = dev->port->ha;  	spin_lock_irqsave(dev->sata_dev.ap->lock, flags); -	if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD) { +	if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || +	    ((stat->stat == SAM_STAT_CHECK_CONDITION && +	      dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {  		ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);  		qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);  		dev->sata_dev.sstatus = resp->sstatus;  		dev->sata_dev.serror = resp->serror;  		dev->sata_dev.scontrol = resp->scontrol; -	} else if (stat->stat != SAM_STAT_GOOD) { +	} else {  		ac = sas_to_ata_err(stat);  		if (ac) {  			SAS_DPRINTK("%s: SAS error %x\n", __func__, @@ -305,55 +307,6 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc)  	}  } -static int sas_ata_scr_write(struct ata_link *link, unsigned int sc_reg_in, -			      u32 val) -{ -	struct domain_device *dev = link->ap->private_data; - -	SAS_DPRINTK("STUB %s\n", __func__); -	switch (sc_reg_in) { -		case SCR_STATUS: -			dev->sata_dev.sstatus = val; -			break; -		case SCR_CONTROL: -			dev->sata_dev.scontrol = val; -			break; -		case SCR_ERROR: -			dev->sata_dev.serror = val; -			break; -		case SCR_ACTIVE: -			dev->sata_dev.ap->link.sactive = val; -			break; -		default: -			return -EINVAL; -	} -	return 0; -} - -static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in, -			    u32 *val) -{ -	struct domain_device *dev = link->ap->private_data; - -	SAS_DPRINTK("STUB %s\n", __func__); -	switch (sc_reg_in) { -		case SCR_STATUS: -			*val = dev->sata_dev.sstatus; -			return 0; -		case SCR_CONTROL: -			*val = dev->sata_dev.scontrol; -			return 0; -		case SCR_ERROR: -			*val = dev->sata_dev.serror; -			return 0; -		case SCR_ACTIVE: -			*val = dev->sata_dev.ap->link.sactive; -			return 0; -		default: -			return -EINVAL; -	} -} -  static struct ata_port_operations sas_sata_ops = {  	.prereset		= ata_std_prereset,  	.softreset		= NULL, @@ -367,8 +320,6 @@ static struct ata_port_operations sas_sata_ops = {  	.qc_fill_rtf		= sas_ata_qc_fill_rtf,  	.port_start		= ata_sas_port_start,  	.port_stop		= ata_sas_port_stop, -	.scr_read		= sas_ata_scr_read, -	.scr_write		= sas_ata_scr_write  };  static struct ata_port_info sata_port_info = { @@ -801,7 +752,7 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost)  		if (!dev_is_sata(ddev))  			continue; -		 +  		ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler");  		ata_scsi_port_error_handler(shost, ap);  	} @@ -834,13 +785,13 @@ int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,  		LIST_HEAD(sata_q);  		ap = NULL; -		 +  		list_for_each_entry_safe(cmd, n, work_q, eh_entry) {  			struct domain_device *ddev = cmd_to_domain_dev(cmd);  			if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))  				continue; -			if(ap && ap != ddev->sata_dev.ap) +			if (ap && ap != ddev->sata_dev.ap)  				continue;  			ap = ddev->sata_dev.ap;  			rtn = 1; @@ -848,8 +799,21 @@ int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,  		}  		if (!list_empty(&sata_q)) { -			ata_port_printk(ap, KERN_DEBUG,"sas eh calling libata cmd error handler\n"); +			ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata cmd error handler\n");  			ata_scsi_cmd_error_handler(shost, ap, &sata_q); +			/* +			 * ata's error handler may leave the cmd on the list +			 * so make sure they don't remain on a stack list +			 * about to go out of scope. +			 * +			 * This looks strange, since the commands are +			 * now part of no list, but the next error +			 * action will be ata_port_error_handler() +			 * which takes no list and sweeps them up +			 * anyway from the ata tag array. +			 */ +			while (!list_empty(&sata_q)) +				list_del_init(sata_q.next);  		}  	} while (ap);  |