diff options
Diffstat (limited to 'drivers/ata/libata-scsi.c')
| -rw-r--r-- | drivers/ata/libata-scsi.c | 58 | 
1 files changed, 48 insertions, 10 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index e093c7a7deeb..551077cea4e4 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2694,18 +2694,36 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)  	return 0;  } -static struct ata_device *ata_find_dev(struct ata_port *ap, int devno) +static struct ata_device *ata_find_dev(struct ata_port *ap, unsigned int devno)  { -	if (!sata_pmp_attached(ap)) { -		if (likely(devno >= 0 && -			   devno < ata_link_max_devices(&ap->link))) +	/* +	 * For the non-PMP case, ata_link_max_devices() returns 1 (SATA case), +	 * or 2 (IDE master + slave case). However, the former case includes +	 * libsas hosted devices which are numbered per scsi host, leading +	 * to devno potentially being larger than 0 but with each struct +	 * ata_device having its own struct ata_port and struct ata_link. +	 * To accommodate these, ignore devno and always use device number 0. +	 */ +	if (likely(!sata_pmp_attached(ap))) { +		int link_max_devices = ata_link_max_devices(&ap->link); + +		if (link_max_devices == 1) +			return &ap->link.device[0]; + +		if (devno < link_max_devices)  			return &ap->link.device[devno]; -	} else { -		if (likely(devno >= 0 && -			   devno < ap->nr_pmp_links)) -			return &ap->pmp_link[devno].device[0]; + +		return NULL;  	} +	/* +	 * For PMP-attached devices, the device number corresponds to C +	 * (channel) of SCSI [H:C:I:L], indicating the port pmp link +	 * for the device. +	 */ +	if (devno < ap->nr_pmp_links) +		return &ap->pmp_link[devno].device[0]; +  	return NULL;  } @@ -4186,7 +4204,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)  	scsi_done(cmd);  } -int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) +int ata_scsi_add_hosts(struct ata_host *host, const struct scsi_host_template *sht)  {  	int i, rc; @@ -4579,10 +4597,11 @@ int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,  void ata_scsi_dev_rescan(struct work_struct *work)  {  	struct ata_port *ap = -		container_of(work, struct ata_port, scsi_rescan_task); +		container_of(work, struct ata_port, scsi_rescan_task.work);  	struct ata_link *link;  	struct ata_device *dev;  	unsigned long flags; +	bool delay_rescan = false;  	mutex_lock(&ap->scsi_scan_mutex);  	spin_lock_irqsave(ap->lock, flags); @@ -4596,6 +4615,21 @@ void ata_scsi_dev_rescan(struct work_struct *work)  			if (scsi_device_get(sdev))  				continue; +			/* +			 * If the rescan work was scheduled because of a resume +			 * event, the port is already fully resumed, but the +			 * SCSI device may not yet be fully resumed. In such +			 * case, executing scsi_rescan_device() may cause a +			 * deadlock with the PM code on device_lock(). Prevent +			 * this by giving up and retrying rescan after a short +			 * delay. +			 */ +			delay_rescan = sdev->sdev_gendev.power.is_suspended; +			if (delay_rescan) { +				scsi_device_put(sdev); +				break; +			} +  			spin_unlock_irqrestore(ap->lock, flags);  			scsi_rescan_device(&(sdev->sdev_gendev));  			scsi_device_put(sdev); @@ -4605,4 +4639,8 @@ void ata_scsi_dev_rescan(struct work_struct *work)  	spin_unlock_irqrestore(ap->lock, flags);  	mutex_unlock(&ap->scsi_scan_mutex); + +	if (delay_rescan) +		schedule_delayed_work(&ap->scsi_rescan_task, +				      msecs_to_jiffies(5));  }  |