libata: support the ata host which implements a queue depth less than 32
The sata on fsl mpc8315e is broken after the commit8a4aeec8d2("libata/ahci: accommodate tag ordered controllers"). The reason is that the ata controller on this SoC only implement a queue depth of 16. When issuing the commands in tag order, all the commands in tag 16 ~ 31 are mapped to tag 0 unconditionally and then causes the sata malfunction. It makes no senses to use a 32 queue in software while the hardware has less queue depth. So consider the queue depth implemented by the hardware when requesting a command tag. Fixes:8a4aeec8d2("libata/ahci: accommodate tag ordered controllers") Cc: stable@vger.kernel.org Signed-off-by: Kevin Hao <haokexin@gmail.com> Acked-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
		
					parent
					
						
							
								7188b06757
							
						
					
				
			
			
				commit
				
					
						1871ee134b
					
				
			
		
					 1 changed files with 19 additions and 3 deletions
				
			
		|  | @ -4787,6 +4787,10 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) | |||
|  *	ata_qc_new - Request an available ATA command, for queueing | ||||
|  *	@ap: target port | ||||
|  * | ||||
|  *	Some ATA host controllers may implement a queue depth which is less | ||||
|  *	than ATA_MAX_QUEUE. So we shouldn't allocate a tag which is beyond | ||||
|  *	the hardware limitation. | ||||
|  * | ||||
|  *	LOCKING: | ||||
|  *	None. | ||||
|  */ | ||||
|  | @ -4794,14 +4798,16 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) | |||
| static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) | ||||
| { | ||||
| 	struct ata_queued_cmd *qc = NULL; | ||||
| 	unsigned int i, tag; | ||||
| 	unsigned int i, tag, max_queue; | ||||
| 
 | ||||
| 	max_queue = ap->scsi_host->can_queue; | ||||
| 
 | ||||
| 	/* no command while frozen */ | ||||
| 	if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	for (i = 0; i < ATA_MAX_QUEUE; i++) { | ||||
| 		tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE; | ||||
| 	for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) { | ||||
| 		tag = tag < max_queue ? tag : 0; | ||||
| 
 | ||||
| 		/* the last tag is reserved for internal command. */ | ||||
| 		if (tag == ATA_TAG_INTERNAL) | ||||
|  | @ -6169,6 +6175,16 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) | |||
| { | ||||
| 	int i, rc; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The max queue supported by hardware must not be greater than | ||||
| 	 * ATA_MAX_QUEUE. | ||||
| 	 */ | ||||
| 	if (sht->can_queue > ATA_MAX_QUEUE) { | ||||
| 		dev_err(host->dev, "BUG: the hardware max queue is too large\n"); | ||||
| 		WARN_ON(1); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	/* host must have been started */ | ||||
| 	if (!(host->flags & ATA_HOST_STARTED)) { | ||||
| 		dev_err(host->dev, "BUG: trying to register unstarted host\n"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kevin Hao
				Kevin Hao