mirror of
				https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
				synced 2025-11-04 07:44:51 +10:00 
			
		
		
		
	scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans
sas_user_scan() did not fully process wildcard channel scans (SCAN_WILD_CARD) when a transport-specific user_scan() callback was present. Only channel 0 would be scanned via user_scan(), while the remaining channels were skipped, potentially missing devices. user_scan() invokes updated sas_user_scan() for channel 0, and if successful, iteratively scans remaining channels (1 to shost->max_channel) via scsi_scan_host_selected(). This ensures complete wildcard scanning without affecting transport-specific scanning behavior. Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com> Link: https://lore.kernel.org/r/20250624061649.17990-1-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									6e0f6aa44b
								
							
						
					
					
						commit
						37c4e72b06
					
				@ -1900,7 +1900,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(scsi_scan_host_selected);
 | 
			
		||||
static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
 | 
			
		||||
{
 | 
			
		||||
	struct scsi_device *sdev;
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,8 @@
 | 
			
		||||
#include <scsi/scsi_transport_sas.h>
 | 
			
		||||
 | 
			
		||||
#include "scsi_sas_internal.h"
 | 
			
		||||
#include "scsi_priv.h"
 | 
			
		||||
 | 
			
		||||
struct sas_host_attrs {
 | 
			
		||||
	struct list_head rphy_list;
 | 
			
		||||
	struct mutex lock;
 | 
			
		||||
@ -1683,6 +1685,22 @@ int scsi_is_sas_rphy(const struct device *dev)
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(scsi_is_sas_rphy);
 | 
			
		||||
 | 
			
		||||
static void scan_channel_zero(struct Scsi_Host *shost, uint id, u64 lun)
 | 
			
		||||
{
 | 
			
		||||
	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 | 
			
		||||
	struct sas_rphy *rphy;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(rphy, &sas_host->rphy_list, list) {
 | 
			
		||||
		if (rphy->identify.device_type != SAS_END_DEVICE ||
 | 
			
		||||
		    rphy->scsi_target_id == -1)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (id == SCAN_WILD_CARD || id == rphy->scsi_target_id) {
 | 
			
		||||
			scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id,
 | 
			
		||||
					 lun, SCSI_SCAN_MANUAL);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * SCSI scan helper
 | 
			
		||||
@ -1692,23 +1710,41 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
 | 
			
		||||
		uint id, u64 lun)
 | 
			
		||||
{
 | 
			
		||||
	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 | 
			
		||||
	struct sas_rphy *rphy;
 | 
			
		||||
	int res = 0;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&sas_host->lock);
 | 
			
		||||
	list_for_each_entry(rphy, &sas_host->rphy_list, list) {
 | 
			
		||||
		if (rphy->identify.device_type != SAS_END_DEVICE ||
 | 
			
		||||
		    rphy->scsi_target_id == -1)
 | 
			
		||||
			continue;
 | 
			
		||||
	switch (channel) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		mutex_lock(&sas_host->lock);
 | 
			
		||||
		scan_channel_zero(shost, id, lun);
 | 
			
		||||
		mutex_unlock(&sas_host->lock);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
		if ((channel == SCAN_WILD_CARD || channel == 0) &&
 | 
			
		||||
		    (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
 | 
			
		||||
			scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id,
 | 
			
		||||
					 lun, SCSI_SCAN_MANUAL);
 | 
			
		||||
	case SCAN_WILD_CARD:
 | 
			
		||||
		mutex_lock(&sas_host->lock);
 | 
			
		||||
		scan_channel_zero(shost, id, lun);
 | 
			
		||||
		mutex_unlock(&sas_host->lock);
 | 
			
		||||
 | 
			
		||||
		for (i = 1; i <= shost->max_channel; i++) {
 | 
			
		||||
			res = scsi_scan_host_selected(shost, i, id, lun,
 | 
			
		||||
						      SCSI_SCAN_MANUAL);
 | 
			
		||||
			if (res)
 | 
			
		||||
				goto exit_scan;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	mutex_unlock(&sas_host->lock);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
	default:
 | 
			
		||||
		if (channel < shost->max_channel) {
 | 
			
		||||
			res = scsi_scan_host_selected(shost, channel, id, lun,
 | 
			
		||||
						      SCSI_SCAN_MANUAL);
 | 
			
		||||
		} else {
 | 
			
		||||
			res = -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
exit_scan:
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user